PHP: Атрибуты для добавления метаданных
Атрибуты, введённые в PHP 8, представляют собой способ добавления метаданных к классам, методам, функциям, параметрам, свойствам и т.д. в виде аннотаций, что делает код более читаемым и позволяет избегать использования документационных комментариев для этих целей. Атрибуты можно использовать для самых разных задач, например, для указания конфигураций роутинга в веб-приложениях, валидации данных или кэширования.
В PHP атрибуты объявляются через двойные квадратные скобки #[AttributeName]. Вот пример использования атрибута:
#[Attribute] class MyAttribute { public function __construct( public string $value ) { } } #[MyAttribute(value: "Пример использования атрибута")] class MyClass { }
Получить информацию об атрибутах можно с помощью Отражений (Reflection API):
$reflectionClass = new ReflectionClass( MyClass::class ); $attributes = $reflectionClass->getAttributes(); foreach( $attributes as $attribute ) { $instance = $attribute->newInstance(); var_dump( $instance ); #> object(MyAttribute)#3 (1) { ["value"]=> string(56) "Пример использования атрибута" } echo $instance->value; #> Пример использования атрибута }
Расширенный пример с пространством имён и получением атрибута метода класса
namespace MyExampleNamespace; use Attribute; use ReflectionClass; use ReflectionMethod; #[Attribute] class MyAttribute { public function __construct(public string $value) { } } #[Attribute] class MethodAttribute { public function __construct(public string $description) { } } #[MyAttribute(value: "Пример использования атрибута с namespace")] class MyClass { #[MethodAttribute(description: "Пример атрибута для метода")] public function myMethod() { return "Метод с атрибутом"; } } # Получаем информацию об атрибутах класса $reflectionClass = new ReflectionClass( MyClass::class ); $classAttributes = $reflectionClass->getAttributes(); foreach( $classAttributes as $attribute ) { $instance = $attribute->newInstance(); echo "Класс атрибут: " . $instance->value . "\n"; } # Получаем информацию об атрибутах метода $reflectionMethod = new ReflectionMethod( MyClass::class, 'myMethod' ); $methodAttributes = $reflectionMethod->getAttributes(); foreach( $methodAttributes as $attribute ) { $instance = $attribute->newInstance(); echo "Метод атрибут: " . $instance->description . "\n"; }
Расширенный пример, где класс атрибута содержит свой метод, константу и аргумент
namespace MyExampleNamespace; use Attribute; use ReflectionClass; use ReflectionMethod; #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] class MyAttribute { const EXAMPLE_CONSTANT = 'Пример константы'; public function __construct( public string $value ) { } public function customMethod(): string { return "Значение аргумента: {$this->value}, константа: " . self::EXAMPLE_CONSTANT; } } #[MyAttribute(value: "Пример использования атрибута с namespace для класса")] class MyClass { #[MyAttribute(value: "Пример использования атрибута для метода")] public function myMethod() { # Тело метода } } # Получаем информацию об атрибутах класса $reflectionClass = new ReflectionClass( MyClass::class ); $classAttributes = $reflectionClass->getAttributes(); foreach( $classAttributes as $attribute ) { $instance = $attribute->newInstance(); echo $instance->customMethod() . PHP_EOL; } # Получаем информацию об атрибутах метода $reflectionMethod = new ReflectionMethod( MyClass::class, 'myMethod' ); $methodAttributes = $reflectionMethod->getAttributes(); foreach( $methodAttributes as $attribute ) { $instance = $attribute->newInstance(); echo $instance->customMethod() . PHP_EOL; }
Комментарии