PHP 8.0 представив attributes — першокласний спосіб додавати структуровані метадані до класів, методів, властивостей тощо. Але читати їх програмно через native reflection API довго й шаблонно. Spatie's PHP Attribute Reader упаковує цей шаблонний код у зручний статичний API.
Наприклад, читання одного class attribute через native reflection API виглядає так:
$reflectionClass = new ReflectionClass(PostController::class);
$attributes = $reflectionClass->getAttributes(Route::class);
if (count($attributes) > 0) {
$route = $attributes[0]->newInstance();
}
Уявіть тепер, що треба робити це для кожного методу, властивості, константи й параметра класу.
Встановлення
composer require spatie/php-attribute-reader
Читання attributes
Пакет надає один клас Attributes із статичними методами для всіх операцій читання. Викличте get(), передавши цільовий клас першим аргументом, а клас attribute — другим, щоб отримати інстанційований об’єкт attribute або null, якщо його немає:
Припустимо, ми визначили власний attribute Route і використали його в контролері:
use App\Attributes\Route;
#[Route('/posts', methods: ['GET'])]
class PostController
{
// ...
}
Отримати або перевірити наявність цього attribute можна так:
use Spatie\Attributes\Attributes;
use App\Attributes\Route;
$route = Attributes::get(PostController::class, Route::class);
Attributes::has(PostController::class, Route::class); // true or false
Для методів, властивостей, констант і параметрів є спеціальні методи:
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);
Кожен повертає інстанційований об’єкт attribute або null, якщо його не знайдено.
Пошук attributes у класі
Attributes::find() шукає всі використання заданого attribute в межах класу — у визначенні класу, методах, властивостях, константах і параметрах — одним викликом.
Наприклад, якщо ми маємо власний attribute Validate і застосували його в такому класі:
use App\Attributes\Validate;
class ContactForm
{
#[Validate('required|string')]
public string $name;
#[Validate('required|email')]
public string $email;
#[Validate('required|string')]
public string $message;
}
Ми можемо знайти всі випадки використання так:
$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
}
Можна також не вказувати клас attribute, щоб отримати всі attributes у класі. Пакет використовує IS_INSTANCEOF для відповідності, тож пошук по базовому класу attribute також знайде підкласи.
PHP Attribute Reader усуває шаблонний код при роботі з reflection. Якщо ви працюєте з кастомними PHP attributes, варто глянути. Вихідний код доступний на GitHub, а повна документація — на spatie.be.