Laravel Packages

A Clean API for Reading PHP Attributes

Published
A Clean API for Reading PHP Attributes image

PHP 8.0 introduced attributes — a first-class way to add structured metadata to classes, methods, properties, and more. But reading them programmatically with the native reflection API is verbose and repetitive. Spatie's PHP Attribute Reader wraps that boilerplate in a clean static API.

For example, reading a single class attribute with the native reflection API looks like this:

$reflectionClass = new ReflectionClass(PostController::class);
$attributes = $reflectionClass->getAttributes(Route::class);
 
if (count($attributes) > 0) {
$route = $attributes[0]->newInstance();
}

Now imagine doing that across every method, property, constant, and parameter of a class.

Installation

composer require spatie/php-attribute-reader

Reading Attributes

The package exposes a single Attributes class with static methods for all reads. Call get() with the target class as the first argument and the attribute class as the second to retrieve an instantiated attribute object, or null if not found:

Assuming we had defined our own custom Route attribute and used it in a controller:

use App\Attributes\Route;
 
#[Route('/posts', methods: ['GET'])]
class PostController
{
// ...
}

We can get or check for that attribute with the following:

use Spatie\Attributes\Attributes;
use App\Attributes\Route;
 
$route = Attributes::get(PostController::class, Route::class);
 
Attributes::has(PostController::class, Route::class); // true or false

For methods, properties, constants, and parameters, the package provides dedicated methods:

Attributes::onMethod(PostController::class, 'index', Middleware::class);
Attributes::onProperty(Post::class, 'title', Column::class);
Attributes::onConstant(PostStatus::class, 'DRAFT', Label::class);
Attributes::onParameter(PostController::class, 'show', 'slug', FromRoute::class);

Each returns the instantiated attribute object, or null if not found.

Finding Attributes Across a Class

Attributes::find() searches for all usages of a given attribute across a class — its class definition, methods, properties, constants, and parameters — in one call.

So if we had our own custom Validate attribute and used it in the following class:

use App\Attributes\Validate;
 
class ContactForm
{
#[Validate('required|string')]
public string $name;
 
#[Validate('required|email')]
public string $email;
 
#[Validate('required|string')]
public string $message;
}

We could then find all usages like this:

$results = Attributes::find(ContactForm::class, Validate::class);
 
foreach ($results as $result) {
$result->name; // e.g. 'name', 'email', 'message'
$result->attribute; // the instantiated attribute object
$result->target; // the underlying Reflection* object
}

You can also omit the attribute class to retrieve every attribute on a class. The package uses IS_INSTANCEOF matching, so searching for a base attribute class will also match subclasses.

PHP Attribute Reader removes the reflection boilerplate from common attribute operations. If you're working with custom PHP attributes, it's worth a look. You can find the source code on GitHub and the full documentation on spatie.be.

Yannick Lyn Fatt photo

Staff Writer at Laravel News and Full stack web developer.

Sponsored

masteringlaravel logo
Laravel Code Review

Get expert guidance in a few days with a Laravel code review

Visit Laravel Code Review

The latest

View all →
Look What You Helped Me Build image

Look What You Helped Me Build

Read article
BashBox: A Sandboxed Bash Interpreter for AI Agents in PHP image

BashBox: A Sandboxed Bash Interpreter for AI Agents in PHP

Read article
Running Laravel's Scheduler on Multiple Servers image

Running Laravel's Scheduler on Multiple Servers

Read article
Laravel Fake Assertions Now Accept Property Arrays image

Laravel Fake Assertions Now Accept Property Arrays

Read article
Route::query() and Model defaults() in Laravel 13.35 image

Route::query() and Model defaults() in Laravel 13.35

Read article
Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat image

Laravel AI SDK 1.1 Adds Agent Skills and Cohere Chat

Read article