spatie/php-attribute-reader
Lightweight PHP 8+ utility to read native attributes from classes, methods, properties, and parameters using reflection. Designed for simple, fast attribute discovery in frameworks and libraries, with an API that fits common annotation-style workflows.
Beyond class-level attributes, you can read attributes from methods, properties, constants, parameters, and standalone functions.
All examples on this page use the following setup:
use Spatie\Attributes\Attributes;
#[Attribute(Attribute::TARGET_METHOD)]
class Route
{
public function __construct(public string $path) {}
}
#[Attribute(Attribute::TARGET_PROPERTY)]
class Column
{
public function __construct(public string $name) {}
}
#[Attribute(Attribute::TARGET_CLASS_CONSTANT)]
class Label
{
public function __construct(public string $text) {}
}
#[Attribute(Attribute::TARGET_PARAMETER)]
class FromQuery
{
public function __construct(public string $key = '') {}
}
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class Middleware
{
public function __construct(public string $name) {}
}
class UserController
{
#[Label('Active')]
public const STATUS_ACTIVE = 'active';
#[Column('email_address')]
public string $email;
#[Route('/users')]
#[Middleware('auth')]
#[Middleware('verified')]
public function index(#[FromQuery('q')] string $query) {}
}
$route = Attributes::onMethod(UserController::class, 'index', Route::class);
$route->path; // '/users'
$column = Attributes::onProperty(UserController::class, 'email', Column::class);
$column->name; // 'email_address'
$label = Attributes::onConstant(UserController::class, 'STATUS_ACTIVE', Label::class);
$label->text; // 'Active'
Specify both the method name and parameter name:
$fromQuery = Attributes::onParameter(UserController::class, 'index', 'query', FromQuery::class);
$fromQuery->key; // 'q'
For standalone functions, use onFunction() with the fully qualified function name. For namespaced functions, you must use the full namespace:
#[Attribute]
class Deprecated
{
public function __construct(public string $reason = '') {}
}
#[Deprecated('Use newHelper() instead')]
function oldHelper() {}
$deprecated = Attributes::onFunction('oldHelper', Deprecated::class);
$deprecated->reason; // 'Use newHelper() instead'
// For namespaced functions, use the fully qualified name:
// Attributes::onFunction('App\Helpers\oldHelper', Deprecated::class);
If the function does not exist, onFunction() returns null.
When an attribute is repeatable, use the getAllOn* methods to retrieve all instances:
$middlewares = Attributes::getAllOnMethod(UserController::class, 'index', Middleware::class);
$middlewares[0]->name; // 'auth'
$middlewares[1]->name; // 'verified'
The same pattern is available for all target types:
Attributes::getAllOnMethod($class, $method, $attribute); // array
Attributes::getAllOnProperty($class, $property, $attribute); // array
Attributes::getAllOnConstant($class, $constant, $attribute); // array
Attributes::getAllOnParameter($class, $method, $parameter, $attribute); // array
Attributes::getAllOnFunction($function, $attribute); // array
All on* and getAllOn* methods accept an optional attribute parameter. When omitted, they return all attributes on that target regardless of type:
// Get the first attribute on a method (any type)
$attribute = Attributes::onMethod(UserController::class, 'index');
// Get all attributes on a property
$attributes = Attributes::getAllOnProperty(UserController::class, 'email');
// Works on all targets
Attributes::onProperty($class, $property);
Attributes::onConstant($class, $constant);
Attributes::onParameter($class, $method, $parameter);
Attributes::onFunction($function);
Attributes::getAllOnMethod($class, $method);
Attributes::getAllOnProperty($class, $property);
Attributes::getAllOnConstant($class, $constant);
Attributes::getAllOnParameter($class, $method, $parameter);
Attributes::getAllOnFunction($function);
The on* methods return null when the target doesn't exist or lacks the attribute. The getAllOn* methods return an empty array. No exceptions are thrown.
Attributes::onMethod(UserController::class, 'nonExistent', Route::class); // null
Attributes::getAllOnMethod(UserController::class, 'nonExistent', Middleware::class); // []
How can I help you explore Laravel packages today?