Компонент PropertyInfo

Дата оновлення перекладу 2025-01-10

Компонент PropertyInfo

Компонент PropertyInfo дозволяє вам отримувати інформацію про властивості класу, використовуючі різні джерела метаданих.

У той час як компонент PropertyAccess дозволяє вам читати та писати значення з/в обʼєкти та масиви, компонент PropertyInfo працює лише з визначеннями класів, щоб надати інформацію про тип даних та видимості властивостей у цьому класі, включно з методами гетер та сетер.

Установка

1
$ composer require symfony/property-info

Note

Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити файл vendor/autoload.phpу вашому коді для включення механізму автозавантаження класів, наданих Composer. Детальніше можна прочитати у цій статті.

Додаткові залежності можуть бути необхідні для деяких з екстракторів, наданих цим компонентом .

Використання

Щоб використати цей компонент, створіть новий екземпляр PropertyInfoExtractor і надайте йому набір екстракторів інформації.

use ExampleNamespaceYourAwesomeCoolClass; use SymfonyComponentPropertyInfoExtractorPhpDocExtractor; use SymfonyComponentPropertyInfoExtractorReflectionExtractor; use SymfonyComponentPropertyInfoPropertyInfoExtractor;

// повний список екстракторів відображено нижче $phpDocExtractor = new PhpDocExtractor(); $reflectionExtractor = new ReflectionExtractor();

// список PropertyListExtractorInterface (будь-яке ітероване) $listExtractors = [$reflectionExtractor];

// список PropertyTypeExtractorInterface (будь-яке ітероване) $typeExtractors = [$phpDocExtractor, $reflectionExtractor];

// список PropertyDescriptionExtractorInterface (будь-яке ітероване) $descriptionExtractors = [$phpDocExtractor];

// список PropertyAccessExtractorInterface (будь-яке ітероване) $accessExtractors = [$reflectionExtractor];

// список PropertyInitializableExtractorInterface (будь-яке ітероване) $propertyInitializableExtractors = [$reflectionExtractor];

$propertyInfo = new PropertyInfoExtractor(
$listExtractors, $typeExtractors, $descriptionExtractors, $accessExtractors, $propertyInitializableExtractors

);

// див. нижче, щоб побачити більше прикладів $class = YourAwesomeCoolClass::class; $properties = $propertyInfo->getProperties($class);

Порядок екстракторів

Порядок екземплярів екстракторів у масиві має значення: перший результат, який не буде null, буде повернено. Тому ви повинні надати кожній категорії екстракторів окремі масиви, навіть якщо екстрактор надає інформацію для більше, ніж однієї категорії.

Наприклад, у той час, як класи ReflectionExtractor і DoctrineExtractor обидва надають інформацію про список та тип, напевно буде краще, щоб:

  • ReflectionExtractor мав пріоритет для інформації про список, щоб всі властивості у класі були повернені (а не тільки відображені властивості).
  • DoctrineExtractor мав проритет для інформації про тип, щоб метадані сутності були використані замість типізування, щоб надати точнішу інформацію про тип.

    use SymfonyBridgeDoctrinePropertyInfoDoctrineExtractor; use SymfonyComponentPropertyInfoExtractorReflectionExtractor; use SymfonyComponentPropertyInfoPropertyInfoExtractor;

    $reflectionExtractor = new ReflectionExtractor(); $doctrineExtractor = new DoctrineExtractor(/ ... /);

    $propertyInfo = new PropertyInfoExtractor(
    // Список екстракторів [ $reflectionExtractor, $doctrineExtractor ], // Тип екстракторів [ $doctrineExtractor, $reflectionExtractor ]

    );

Вилучена інформація

Клас PropertyInfoExtractor демонструє публічні методи для виучення декількох типів інформації:

Note

Передайте імʼя класу, а не обʼєкта, методам екстрактора:

1
2
3
4
5
6
7
// Погано! Може спрацювати, але не з усіма екстракторами
$propertyInfo->getProperties($awesomeObject);

// Добре!
$propertyInfo->getProperties(get_class($awesomeObject));
$propertyInfo->getProperties('Example\Namespace\YourAwesomeClass');
$propertyInfo->getProperties(YourAwesomeClass::class);

Інформація про список

Екстрактори, які реалізують PropertyListExtractorInterface, надають список властивостей, які доступні у класі в якості масиву, що містить кожне імʼя властивості у вигляді рядку.

$properties = $propertyInfo->getProperties($class); / Приклад результату ------------------ array(3) { [0] => string(8) "username" [1] => string(8) "password" [2] => string(6) "active" } /

Інформація про тип

Екстрактори, які реалізують PropertyTypeExtractorInterface, надають обʼємну інформацію про тип даних для властивості.

$types = $propertyInfo->getTypes($class, $property); / Приклад результату ------------------ array(1) { [0] => class SymfonyComponentPropertyInfoType (6) { private $builtinType => string(6) "string" private $nullable => bool(false) private $class => NULL private $collection => bool(false) private $collectionKeyType => NULL private $collectionValueType => NULL } } /

Див. , щоб отримати інформацію про клас Type.

Блок документації

Екстрактори, які реалізують PropertyDocBlockExtractorInterface, можуть надати повний блок документації для властивості у вигляді рядка:

1
2
3
4
5
6
7
8
$docBlock = $propertyInfo->getDocBlock($class, $property);
/*
    Example Result
    --------------
    string(79):
        Це наступний абзац у DocComment.
        Він може охоплювати кілька рядків.
*/

7.1

Інтерфейс PropertyDocBlockExtractorInterface був представлений в Symfony 7.1.

Описова інформація

Екстрактори, які реалізують PropertyDescriptionExtractorInterface, надають короткі та довгі описи з анотації властивостей у вигляді рядків.

$title = $propertyInfo->getShortDescription($class, $property); / Приклад результату ------------------ string(41) "Це перший рядок DocComment." /

$paragraph = $propertyInfo->getLongDescription($class, $property); / Приклад результату ------------------ string(79): Це наступний параграф у DocComment. Він може простягатися на декілька рядків. /

Інформація про доступ

Екстрактори, які реалізують PropertyAccessExtractorInterface, надають інформацію про те, чи можна прочитати або написати властивості у вигляді булевих значень.

$propertyInfo->isReadable($class, $property); // Приклад результату: bool(true)

$propertyInfo->isWritable($class, $property); // Приклад результату: bool(false)

ReflectionExtractor шукає методи гетера/ісера/ сетера/хасера на додаток до того, чи є властивість публічною, щоб визначити, чи можливо отримати до неї доступ. Це засновується на тому, як працює PropertyAccess. Він передбачає використання назв методів у стилі верблюжого регістру відповідно до PSR-1. Наприклад, обидві властивості myProperty і my_property доступні для читання, якщо є метод getMyProperty() і доступні для запису, якщо існує метод setMyProperty().

Інформація про властивість, що можна ініціювати

Екстрактори, які реалізують PropertyInitializableExtractorInterface, надають інформацію про те, чи можна ініціювати властивості через констуктор класу в якості булевих значень:

1
2
$propertyInfo->isInitializable($class, $property);
// Приклад результату: bool(true)

isInitializable() повертає true, якщо параметр конструктора заданого класу співпадає з заданим імʼям властивості.

Tip

Головний клас PropertyInfoExtractor реалізує всі ці інтерфейси, делегуючи вилучення інформації властивості екстракторам, які були зареєстровані у ньому.

Це означає, що будь-який метод, доступний у кожному з екстракторів, також доступний у головному класі PropertyInfoExtractor.

Обʼєкти типів

У порівнянні з іншими екстракторами, екстрактори типу інформації надають набагато більше інформації, ніж можна відобразити у звичайному скалярному значенні. Тому, екстрактори типу повертають масив обʼєктів Type для кожного типу, підтримуваного властивістю.

Наприклад, якщо властивість підтримує як integer, так і string (через анотацію @return int|string), PropertyInfoExtractor::getTypes() поверне масив, що містить два екземпляри класу Type.

Note

Більшість екстракторів повернуть лише один екземпляр Type. На даний момент, PhpDocExtractor є єдиним екстрактором, який повертає декіллька екземплярів у масиві.

Кожний обʼєкт надасть 6 атрибутів, доступних у 6 методах:

Type::getBuiltInType()

Метод Type::getBuiltinType() поверне вбудований тип даних PHP, який може бути одним з цих можливих значень рядку: array, bool, callable, float, int, iterable, null, object, resource або string.

Константи всередині класу Type, у формі Type::BUILTIN_TYPE_* надаються для зручності.

Type::isNullable()

Метод Type::isNullable() поверне булеве значення, що відображає, чи може параметр властивості бути встановлений як null.

Type::getClassName()

Якщо вбудований тип даних PHP - це object, метод Type::getClassName() поверне повне прийнятне імʼя класу або інтерфейсу.

Type::isCollection()

Метод Type::isCollection() поверне булеве значення, що відображує, чи є параметр властивості набором (нескалярним значенням, здатним містити інші значення). На даний момент, повертається true, якщо:

  • Вбудований тип даних PHP - це array;
  • метод заглушення властивості, з якої виводиться властивість, має префікс add або remove , які визначаються у вигляді списку префіксів заглушувачів масиву.
  • Анотація phpDocumentor є типом "колекції" (наприклад, @var SomeClass<DateTime>, @var SomeClass<integer,string>, @var Doctrine\Common\Collections\Collection<App\Entity\SomeEntity> та ін.)

Type::getCollectionKeyType() і Type::getCollectionValueType()

Якщо властивість є набором, можуть бути повернені додаткові типи обʼєктів, як для типу ключів, так і для значень набору (якщо інформація доступна), через методи Type::getCollectionKeyType() і Type::getCollectionValueType().

Note

Псевдо-тип list повертається компонентом PropertyInfo як масив з цілим числом в якості типу ключа.

Екстрактори

Вилучення інформації властивості виконується класами екстракторів. Клас екстрактора може надати один або більше типів інформації властивості, реалізуючи правильний(і) інтерфейс(и).

Клас PropertyInfoExtractor ітерує відповідні класи екстракторів у тому порядку, в якому вони були встановлені, викликає відповідний метод та повертає перший результат, який не є null.

Незважаючи на те, що ви можете створювати свої власні екстрактори, наступні вже доступні для того, щоб охопити більшість випадків використання:

ReflectionExtractor

Використовуючи відображення PHP, ReflectionExtractor надає інформацію про тип, списк та доступ з методів сетера та процесу доступу. Він також може надати тип властивості (навіть вилучаючи його з конструктора аргументів), якщо його можна ініціювати через конструктор. Він підтримує зворотні та скалярні типи:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;

$reflectionExtractor = new ReflectionExtractor();

// Інформація про список.
$reflectionExtractor->getProperties($class);

// Інформація про тип.
$reflectionExtractor->getTypes($class, $property);

// Інформація про доступ.
$reflectionExtractor->isReadable($class, $property);
$reflectionExtractor->isWritable($class, $property);

// Інформація, яку можна ініціювати
$reflectionExtractor->isInitializable($class, $property);

Note

При використанні фреймворку Symfony, цей сервіс автоматично реєструється, коли включена функція property_info:

1
2
3
4
# config/packages/framework.yaml
framework:
    property_info:
        enabled: true

PhpDocExtractor

Note

Цей екстрактор залежить від бібліотеки phpdocumentor/reflection-docblock.

Використовуючи Відображення phpDocumentor для аналізу властивості та методу анотації, PhpDocExtractor надає інформацію про тип та опис. Цей екстрактор автоматично реєструється за допомогою property_info у фреймворку Symfony, якщо наявна залежна бібліотека.

use SymfonyComponentPropertyInfoExtractorPhpDocExtractor;

$phpDocExtractor = new PhpDocExtractor();

// Інформація про тип. $phpDocExtractor->getTypes($class, $property); // Інформація опису. $phpDocExtractor->getShortDescription($class, $property); $phpDocExtractor->getLongDescription($class, $property); $phpDocExtractor->getDocBlock($class, $property);

7.1

Метод getDocBlock() було представлено в Symfony 7.1.

PhpStanExtractor

Note

Цей екстрактор залежить від бібліотек phpstan/phpdoc-parser і phpdocumentor/reflection-docblock.

Цей екстрактор вилучає інформацію завдяки парсеру PHPStan. Він збирає інформацію з анотацій властивостей та методів, таких як @var, @param або @return:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Domain/Foo.php
class Foo
{
    /**
     * @param string $bar
     */
    public function __construct(
        private string $bar,
    ) {
    }
}

// Extraction.php
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
use App\Domain\Foo;

$phpStanExtractor = new PhpStanExtractor();
$phpStanExtractor->getTypesFromConstructor(Foo::class, 'bar');

SerializerExtractor

Note

Цей екстракктор залежить від бібліотеки symfony/serializer.

Використовуючи метадані груп з компонента Serializer, SerializerExtractor надає інформацію про список. Цей екстрактор не реєструється автоматично у сервісі property_info у фреймворку Symfony.

use DoctrineCommonAnnotationsAnnotationReader; use SymfonyComponentPropertyInfoExtractorSerializerExtractor; use SymfonyComponentSerializerMappingFactoryClassMetadataFactory; use SymfonyComponentSerializerMappingLoaderAnnotationLoader;

$serializerClassMetadataFactory = new ClassMetadataFactory(
new AnnotationLoader(new AnnotationReader)

); $serializerExtractor = new SerializerExtractor($serializerClassMetadataFactory);

// опція `serializer_groups` має бути сконфігурована (може бути встановлена як null) $serializerExtractor->getProperties($class, ['serializer_groups' => ['mygroup']]);

Якщо serializer_groups встановлено як null, метадані груп серіалізатора не
перевірятимуться, ае ви отримаєте лише властивості, які розглядаються компонентом Серіалізатор (особливо береться до уваги анотація @Ignore).

DoctrineExtractor

Note

Цей екстрактор залежить від бібліотек symfony/doctrine-bridge і doctrine/orm.

Використовуючи дані відображення сутності з Doctrine ORM, DoctrineExtractor надає інформацію про тип та список. Цей екстрактор не реєструється автоматично сервісом property_info у фреймворку Symfony.

use DoctrineORMEntityManager; use DoctrineORMToolsSetup; use SymfonyBridgeDoctrinePropertyInfoDoctrineExtractor;

$config = Setup::createAnnotationMetadataConfiguration([__DIR__], true); $entityManager = EntityManager::create([ 'driver' => 'pdo_sqlite', // ... ], $config); $doctrineExtractor = new DoctrineExtractor($entityManager);

// List information. $doctrineExtractor->getProperties($class); // Type information. $doctrineExtractor->getTypes($class, $property);

ConstructorExtractor

ConstructorExtractor намагається вилучити інформацію властивостей, використовуючи або PhpStanExtractor, або ReflectionExtractor в аргументах конструктора:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Domain/Foo.php
class Foo
{
    public function __construct(
        private string $bar,
    ) {
    }
}

// Extraction.php
use App\Domain\Foo;
use Symfony\Component\PropertyInfo\Extractor\ConstructorExtractor;

$constructorExtractor = new ConstructorExtractor([new ReflectionExtractor()]);
$constructorExtractor->getTypes(Foo::class, 'bar')[0]->getBuiltinType(); // returns 'string'

Створення ваших власних екстракторів

Ви можете створювати ваші власні екстрактори інформації властивості, створюючи клас, що реалізує один або більше наступних інтерфейсів PropertyAccessExtractorInterface, PropertyDescriptionExtractorInterface, PropertyListExtractorInterface і PropertyTypeExtractorInterface.

Якщо ви включили компоненти PropertyInfo і FrameworkBundle, то ви можете автоматично реєструвати ваш екстрактор за допомогою сервісу property_info, визначаючи його в якості сервісу з одним або декількома наступними тегами:

  • property_info.list_extractor, якщо він надає інформацію про список.
  • property_info.type_extractor, якщо він надає інформацію про тип.
  • property_info.description_extractor, якщо він надає інформацію про опис.
  • property_info.access_extractor, якщо він надає інформацію про доступ.
  • property_info.initializable_extractor якщо він надає інформацію, яку можна ініціювати (перевіряє, чи може властивість бути ініційована через конструктор).