Что это такое атрибуты в PHP 8


Сама концепция атрибутов уже давно известна, мы много лет используем аннотации (докблоки) для добавления каких-то метаданных к классам, свойствам, методам, переменным и т.д. Думаю всем давно известны примеры из PHPUnit, Doctrine ORM, Assert и многих других либок и фреймворков.

Как это работало раньше?

В PHP докблоки «рефлексивны»: к ним можно получить доступ с помощью метода API Reflection getDocComment() на уровне функции, класса, метода и атрибута. Сначала нужно было получить комментарии класса и метода(ов), затем с помощью регулярных выражений распарсить необходимые аннотации. Код выглядел примерно так

$ref = new ReflectionClass(CopyFile::Class);

//получаем комментарии к классу
$methodComments = $ref->getMethod('someAction')->getDocComment();
print $methodComments;

//регулярное выражение для получения аннотации
//в зависимости от вашего типа аннотации оно может отличаться
$pattern = "##";

//получаем все аннотации для классаpreg_match_all($pattern, $methodComments, $matches);

print_r($matches);
Как это работает сейчас и в чём разница?

Атрибуты дают фактически те-же возможности, однако этот способ конфигурации встроен непосредственно в язык, что даёт преимущество в скорости и читабельности. Если раньше некоторые не использовали аннотации, аргументируя это тем, что аннотации - по сути комментарии и не могут быть кодом для выполнения, а так же, функционал, который их использует, сложно распространять, то сейчас это часть языка. Вот так это может выглядеть теперь

$reflection = new ReflectionClass(CopyFile::Class);
$attributes = $reflection->getAttributes();

//или для методов

foreach ($reflection->getMethods() as $method){
	$attributes = $method->getAttributes(SomeAttribute::Class); // выбираем конретный атрибут
	
	if (count($attributes) > 0) {
		$methodName = $method->getName();
		$actionHandler->$methodName();
	}
}
Также можно (а согласно документации даже очень нужно) создавать классы атрибутов для этого нужно использовать атрибут #[Attribute], который можно импортировать из глобального пространства имён

use Attribute;

#[Attribute]
class MyAttribute{
}
с помощью оператора use. Они могут быть пустыми, но так-же могут содержать дополнительную информацию

#[Attribute]
class MyAttribute{
	public $value;
	
	public function __construct($value){
		$this->$value = $value;
	}
}

#[MyAttribute](value: 123)
class Thing{
}
, в виде параметров которые также легко можно прочитать:

$attributes = $reflection->getAttributes(MyAttribute::class);
foreach ($attributes as $attribute) {
    $attribute->getArguments();
}
Как вы поняли из примера, параметры будут переданы в конструктор класса MyAttribute. Параметры могут быть простыми скалярными типами, массивами, константами и т.д.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, php, атрибуты




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Уроки по JavaScript
Охотник Любомир
История одной и решение любой проблемы с сайтом