Как в PHP получить доступ к аннотациям (или DocBlock) класса или метода, чтобы их прочитать?

«Как в PHP получить доступ к аннотациям (или DocBlock) класса или метода, чтобы их прочитать?» — вопрос из категории PHP Core, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для чтения DocBlock-комментариев (часто называемых аннотациями) в PHP используется встроенное Reflection API. Сам комментарий извлекается как строка, которую затем нужно пропарсить.

1. Извлечение сырого DocBlock: Используем классы ReflectionClass, ReflectionMethod и т.д.

/**
 * Это описание класса.
 * @ORMEntity(repositoryClass="AppRepositoryProductRepository")
 * @CustomAnnotation(param="value")
 */
class Product {
    /**
     * @ORMColumn(type="string", length=255)
     * @AssertNotBlank()
     */
    private $name;
}

// Получаем Reflection объекта
$classReflection = new ReflectionClass(Product::class);
$methodReflection = new ReflectionMethod(Product::class, 'someMethod');
$propertyReflection = new ReflectionProperty(Product::class, 'name');

// Извлекаем DocBlock
$classDocComment = $classReflection->getDocComment(); // Возвращает строку или false
$propertyDocComment = $propertyReflection->getDocComment();

2. Парсинг аннотаций: Сырую строку редко парсят вручную. Стандартом де-факто является библиотека doctrine/annotations.

use DoctrineCommonAnnotationsAnnotationReader;

$reader = new AnnotationReader();

// Чтение аннотации сущности Doctrine с класса
$entityAnnotation = $reader->getClassAnnotation($classReflection, 'DoctrineORMMappingEntity');
if ($entityAnnotation) {
    echo $entityAnnotation->repositoryClass; // Выведет: AppRepositoryProductRepository
}

// Чтение аннотации с свойства
$columnAnnotations = $reader->getPropertyAnnotation($propertyReflection, 'DoctrineORMMappingColumn');
if ($columnAnnotations) {
    echo $columnAnnotations->type; // Выведет: string
}

Важные замечания:

  • Метод getDocComment() возвращает только комментарий, начинающийся с /**. Комментарии // или /* не будут получены.
  • В PHP 8+ появились нативные атрибуты (#[Attribute]), которые являются предпочтительной альтернативой DocBlock-аннотациям. Для их чтения используется ReflectionClass::getAttributes().