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

Ответ

Атрибуты (Attributes) — это форма структурных метаданных, добавленная в PHP 8.0. Они позволяют добавлять декларативную информацию к классам, методам, свойствам, параметрам функций и другим сущностям кода. Эта информация затем может быть прочитана во время выполнения с помощью Reflection API и использована для различных целей: маршрутизации, валидации, конфигурации ORM и т.д.

Ключевые особенности:

  • Объявляются с помощью синтаксиса #[...].
  • Могут иметь параметры, передаваемые в конструктор.
  • Могут быть ограничены определёнными типами сущностей (только классы, только методы и т.п.).

Пример создания и использования атрибута для маршрутизации:

<?php

// 1. Объявляем собственный атрибут
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
class Route
{
    public function __construct(
        public string $path,
        public string $method = 'GET'
    ) {}
}

// 2. Применяем атрибут к классу и методу
#[Route('/api/user')]
class UserController
{
    #[Route('/profile', 'GET')]
    public function getProfile(): array
    {
        return ['name' => 'John'];
    }

    #[Route('/update', 'POST')]
    public function updateProfile(): void {}
}

// 3. Чтение атрибутов через Reflection
$reflectionClass = new ReflectionClass(UserController::class);
$classRoute = $reflectionClass->getAttributes(Route::class)[0] ?? null;
if ($classRoute) {
    $routeInstance = $classRoute->newInstance();
    echo 'Базовый путь контроллера: ' . $routeInstance->path; // Выведет: /api/user
}

$reflectionMethod = new ReflectionMethod(UserController::class, 'getProfile');
$methodRoute = $reflectionMethod->getAttributes(Route::class)[0]->newInstance();
echo 'Метод запроса: ' . $methodRoute->method; // Выведет: GET

Практическое применение: Современные PHP-фреймворки (Symfony, Laravel 8+) активно используют атрибуты вместо аннотаций в док-блоках для конфигурации маршрутов, валидации полей (#[AssertEmail]), описания сущностей Doctrine ORM (#[ORMEntity]) и регистрации слушателей событий.

Ответ 18+ 🔞

Да ты посмотри, что эти умники в PHP придумали! Атрибуты, блядь. Ну в рот меня чих-пых, как будто на дворе 2002-й год и все только про аннотации в комментах слышали. А тут — атрибуты (Attributes). Это, типа, такие метаданные структурные, которые с PHP 8.0 можно прямо в код пихать. Не в докблок, сука, а прям рядом с классом или методом. Информация декларативная, её потом через отражение (Reflection API) можно вычитать и использовать для всякой магии: маршрутизации, валидации, настройки ORM и прочей ерунды.

Что за фигня и как выглядит:

  • Объявляются через #[...]. Просто, ёпта.
  • Могут с параметрами быть, которые в конструктор пихаются.
  • Можно ограничить, куда их вообще можно цеплять — только на классы, только на методы и так далее. Удобно, блядь, доверия ебать ноль, а то какой-нибудь распиздяй на свой нос атрибут навесит.

Смотри, как это в жизни работает, на примере маршрутизации:

<?php

// 1. Объявляем свой собственный атрибут. Создаём класс.
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
class Route
{
    public function __construct(
        public string $path,
        public string $method = 'GET'
    ) {}
}

// 2. Вешаем эту бижутерию на класс и методы.
#[Route('/api/user')]
class UserController
{
    #[Route('/profile', 'GET')]
    public function getProfile(): array
    {
        return ['name' => 'John'];
    }

    #[Route('/update', 'POST')]
    public function updateProfile(): void {}
}

// 3. А теперь, внимание, читаем это всё через Reflection! Вот где магия начинается.
$reflectionClass = new ReflectionClass(UserController::class);
$classRoute = $reflectionClass->getAttributes(Route::class)[0] ?? null;
if ($classRoute) {
    $routeInstance = $classRoute->newInstance();
    echo 'Базовый путь контроллера: ' . $routeInstance->path; // Выведет: /api/user
}

$reflectionMethod = new ReflectionMethod(UserController::class, 'getProfile');
$methodRoute = $reflectionMethod->getAttributes(Route::class)[0]->newInstance();
echo 'Метод запроса: ' . $methodRoute->method; // Выведет: GET

А где это, блядь, реально нужно? Да везде, ёпта! Все эти модные фреймворки — Symfony, Larabel — уже вовсю используют. Вместо того чтобы хуй с горы в комментариях писать (@Route), теперь пишут #[Route]. Или для валидации: #[AssertEmail]. Или для базы данных в Doctrine: #[ORMEntity]. Красота, убей бог. Всё чисто, всё на виду, и терпения ноль ебать парсить какие-то строки в phpDoc.