Компонент PropertyInfo

Дата оновлення перекладу 2022-12-12

Компонент 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 демонструє публічні методи для виучення декількох типів інформації:

  • Список властивостей : `getProperties()`
  • Тип властивості : `getTypes()`
  • Опис властивості : `getShortDescription()` і `getLongDescription()`
  • Доступ до деталей властивості : `isReadable()` і `isWritable()`
  • Властивість, яку можна ініціювати через конструктор : isInitializable()

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.

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

Екстрактори, які реалізують 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.

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

Екстрактори, які реалізують 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().

Екстрактори

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

Клас 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);

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
{
    private $bar;

    /**
     * @param string $bar
     */
    public function __construct($bar) {
        $this->bar = $bar;
    }
}

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

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

6.1

PhpStanExtractor був представлений в Symfony 6.1.

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);

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

Ви можете створювати ваші власні екстрактори інформації властивості, створюючи клас, що реалізує один або більше наступних інтерфейсів 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 якщо він надає інформацію, яку можна ініціювати (перевіряє, чи може властивість бути ініційована через конструктор).