PHPackages                             dentelis/php7-attribute-reader - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. dentelis/php7-attribute-reader

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

dentelis/php7-attribute-reader
==============================

Library for reading php8 attributes from legacy php7 code

00PHP

Since Apr 20Pushed 2mo agoCompare

[ Source](https://github.com/dentelis/php7-attribute-reader)[ Packagist](https://packagist.org/packages/dentelis/php7-attribute-reader)[ RSS](/packages/dentelis-php7-attribute-reader/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependenciesVersions (1)Used By (0)

PHP7 Attribute Reader
=====================

[](#php7-attribute-reader)

A library that brings PHP 8 attribute syntax to PHP 7.2+. The API mirrors PHP 8's native `ReflectionAttribute` as closely as possible, making future migration trivial.

[![PHP Version](https://camo.githubusercontent.com/cd59ba2b0fddd0cb8a2521a4879d8e1f669d27280c478976a54f08dc3bc59db1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344372e322d626c75652e737667)](https://php.net/)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)

Installation
------------

[](#installation)

```
composer require dentelis/php7-attribute-reader
```

Quick Start
-----------

[](#quick-start)

```
use AttributeReader\ReflectionMethodWithAttributes;

class UserController
{
    #[Route('/api/users', 'GET')]
    #[Auth('admin')]
    public function getUsers() {}
}

$method = new ReflectionMethodWithAttributes(UserController::class, 'getUsers');
$attributes = $method->getAttributes();

foreach ($attributes as $attr) {
    echo $attr->getName();          // FQCN, e.g. "App\Attributes\Route"
    print_r($attr->getArguments()); // ['/api/users', 'GET']
    $instance = $attr->newInstance(); // Route object
}
```

Comparison with PHP 8
---------------------

[](#comparison-with-php-8)

```
// PHP 8 native:
$method = new ReflectionMethod(UserController::class, 'getUsers');
$attrs = $method->getAttributes(Route::class);
$route = $attrs[0]->newInstance();

// This library (PHP 7.2+):
$method = new ReflectionMethodWithAttributes(UserController::class, 'getUsers');
$attrs = $method->getAttributes(Route::class);
$route = $attrs[0]->newInstance();
```

Migration to PHP 8: replace `new ReflectionMethodWithAttributes(...)` with `new ReflectionMethod(...)`.

Reflection Classes
------------------

[](#reflection-classes)

The library provides drop-in wrappers for all four PHP reflection types. Each wrapper exposes `getAttributes()` with the same signature as PHP 8, and delegates all other method calls to the underlying reflection object.

### `ReflectionMethodWithAttributes`

[](#reflectionmethodwithattributes)

```
use AttributeReader\ReflectionMethodWithAttributes;

$method = new ReflectionMethodWithAttributes(UserController::class, 'getUsers');

// All attributes
$attrs = $method->getAttributes();

// Filter by exact class
$attrs = $method->getAttributes(Route::class);

// Filter by parent class (includes subclasses)
$attrs = $method->getAttributes(BaseAttribute::class, Attribute::IS_INSTANCEOF);

// Delegates to ReflectionMethod
echo $method->getName();
echo $method->getDeclaringClass()->getName();
```

### `ReflectionClassWithAttributes`

[](#reflectionclasswithattributes)

```
use AttributeReader\ReflectionClassWithAttributes;

#[Controller('/api')]
#[Auth('admin')]
class UserController {}

$class = new ReflectionClassWithAttributes(UserController::class);
// or pass an object:
$class = new ReflectionClassWithAttributes(new UserController());

$attrs = $class->getAttributes();
$attrs = $class->getAttributes(Controller::class);

// Delegates to ReflectionClass
echo $class->getName();
$class->getMethods();
```

### `ReflectionPropertyWithAttributes`

[](#reflectionpropertywithattributes)

```
use AttributeReader\ReflectionPropertyWithAttributes;

class User {
    #[Column('email', unique: true)]
    public $email;
}

$prop = new ReflectionPropertyWithAttributes(User::class, 'email');
$attrs = $prop->getAttributes();
$attrs = $prop->getAttributes(Column::class);

// Delegates to ReflectionProperty
echo $prop->getName();
$prop->isPublic();
```

### `ReflectionFunctionWithAttributes`

[](#reflectionfunctionwithattributes)

```
use AttributeReader\ReflectionFunctionWithAttributes;

#[Route('/handler')]
function myHandler() {}

$func = new ReflectionFunctionWithAttributes('myHandler');
$attrs = $func->getAttributes();
$attrs = $func->getAttributes(Route::class);

// Delegates to ReflectionFunction
echo $func->getName();
```

`getAttributes()` Signature
---------------------------

[](#getattributes-signature)

All four wrapper classes share the same `getAttributes()` signature:

```
getAttributes(?string $name = null, int $flags = 0): Attribute[]
```

**Parameters:**

- `$name` — filter by FQCN (exact match by default)
- `$flags` — `0` (default) or `Attribute::IS_INSTANCEOF` (includes subclasses)

`Attribute` — Returned Object
-----------------------------

[](#attribute--returned-object)

```
$attr->getName(): string;        // Fully qualified class name
$attr->getArguments(): array;    // Parsed arguments (positional and/or named)
$attr->newInstance(): object;    // Instantiates the attribute class
$attr->isRepeated(): bool;       // True if the same attribute appears more than once
```

**Constants:**

- `Attribute::IS_INSTANCEOF = 2` — matches `ReflectionAttribute::IS_INSTANCEOF`

Features
--------

[](#features)

### Filtering

[](#filtering)

```
$method = new ReflectionMethodWithAttributes(Controller::class, 'index');

// All attributes
$all = $method->getAttributes();

// By exact class
$routes = $method->getAttributes(Route::class);

// By parent class (includes subclasses)
$all = $method->getAttributes(BaseAttribute::class, Attribute::IS_INSTANCEOF);
```

### Named Arguments

[](#named-arguments)

```
#[Route(path: '/users', method: 'POST')]
#[Cache(ttl: 3600, enabled: true)]
#[Route('/api/users', method: 'POST')]  // mixed positional and named
```

### Multiple Attributes

[](#multiple-attributes)

```
// Separate lines
#[Route('/admin')]
#[Auth('admin')]
public function dashboard() {}

// Comma-separated
#[Route('/admin'), Auth('admin')]
public function dashboard() {}
```

### Repeated Attributes

[](#repeated-attributes)

```
#[Middleware('auth')]
#[Middleware('logging')]
public function index() {}

$method = new ReflectionMethodWithAttributes(Controller::class, 'index');
$attrs = $method->getAttributes();
$attrs[0]->isRepeated(); // true
```

### Expressions in Arguments

[](#expressions-in-arguments)

Arithmetic, bitwise, and string concatenation with correct operator precedence:

```
#[Cache(ttl: 60 * 60 * 24)]            // 86400
#[Cache(ttl: (2 + 3) * 10)]            // 50
#[Route(path: '/api' . '/users')]       // '/api/users'
#[Config(flags: 1 | 2 | 4)]            // 7
#[Cache(ttl: 2 ** 10)]                 // 1024
```

Supported operators: `+`, `-`, `*`, `/`, `%`, `**`, `.`, `|`, `&`, `^`, `~`, ``

### Constants in Arguments

[](#constants-in-arguments)

Class constants, aliased imports, and global constants:

```
use App\Config\Limits;
use App\Config\Limits as L;

#[Cache(ttl: Limits::DEFAULT_TTL)]         // resolved via use statement
#[Cache(ttl: L::DEFAULT_TTL)]              // aliases work too
#[Cache(ttl: Limits::DEFAULT_TTL * 2)]     // expressions with constants
#[Cache(ttl: PHP_INT_SIZE)]                // global PHP constants
#[Config(name: Limits::APP_NAME . '-prod')]// concatenation with constants
```

Attribute Name Resolution
-------------------------

[](#attribute-name-resolution)

Attribute names are automatically resolved to FQCNs using the file's `use` statements and namespace — no explicit mapping required.

```
// In the source file:
use App\Attributes\Route;

#[Route('/users')]  // Resolved to "App\Attributes\Route"
```

---

Alternative: Static `AttributeReader` API
-----------------------------------------

[](#alternative-static-attributereader-api)

If you prefer not to use wrapper classes, `AttributeReader` exposes static methods that accept standard PHP reflection objects directly:

```
use AttributeReader\AttributeReader;

// Method attributes
AttributeReader::getMethodAttributes(ReflectionMethod $method, ?string $name = null, int $flags = 0): array;

// Class attributes
AttributeReader::getClassAttributes(ReflectionClass $class, ?string $name = null, int $flags = 0): array;

// Property attributes
AttributeReader::getPropertyAttributes(ReflectionProperty $property, ?string $name = null, int $flags = 0): array;

// Function attributes
AttributeReader::getFunctionAttributes(ReflectionFunction $function, ?string $name = null, int $flags = 0): array;
```

Example:

```
$method = new ReflectionMethod(UserController::class, 'getUsers');
$attrs = AttributeReader::getMethodAttributes($method, Route::class);
$route = $attrs[0]->newInstance();
```

---

Testing
-------

[](#testing)

```
composer test
```

Requirements
------------

[](#requirements)

- PHP 7.2 or higher

License
-------

[](#license)

MIT

Credits
-------

[](#credits)

Developed by [Dim Entelis](https://github.com/dentelis/)

###  Health Score

19

—

LowBetter than 9% of packages

Maintenance58

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/5281445?v=4)[Dim Entelis](/maintainers/dentelis)[@dentelis](https://github.com/dentelis)

---

Top Contributors

[![dentelis](https://avatars.githubusercontent.com/u/5281445?v=4)](https://github.com/dentelis "dentelis (15 commits)")

### Embed Badge

![Health badge](/badges/dentelis-php7-attribute-reader/health.svg)

```
[![Health](https://phpackages.com/badges/dentelis-php7-attribute-reader/health.svg)](https://phpackages.com/packages/dentelis-php7-attribute-reader)
```

###  Alternatives

[mothership/state_machine

php implementation of state machine, completely configured by an external .yml file with the render of a graph's description

122.5k1](/packages/mothership-state-machine)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
