Компонент PropertyInfo (Информация о свойстве)

Дата обновления перевода 2024-07-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(
    // Экстраторы списка array( $reflectionExtractor, $doctrineExtractor ), // Экстраторы типа array( $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, предоставляют расширенную информацию типа данных для свойства:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$types = $propertyInfo->getTypes($class, $property);
/*
  Пример результата
  -----------------
  array(1) {
    [0] =>
    class Symfony\Component\PropertyInfo\Type (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);
/*
    Пример результата
    -----------------
    string(79):
        Это следующий параграф в DocComment.
        Он может содержать несколько строк.
*/

7.1

Интерфейс PropertyDocBlockExtractorInterface был представлен в Symfony 7.1.

Информация об описании

Экстракторы, которые реализуют PropertyDescriptionExtractorInterface, предоставляют короткие и длинные описания из аннотации свойств в виде строк:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$title = $propertyInfo->getShortDescription($class, $property);
/*
    Пример результата
    -----------------
    string(41) "Это первая строка DocComment."
*/

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

Информация доступа

Экстракторы, которые реализуют PropertyAccessExtractorInterface, предоставляют информацию о том, можно ли прочитать или написать свойства, в виде булевых значений:

1
2
3
4
5
$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. class.

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::getCollectionKeyTypes() и Type::getCollectionValueTypes()

Если свойство является набором, могут быть возвращены дополнительные типы объектов, как для типа ключей, так и значений набора (если информация доступна), через методы 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, если присутствует зависимая библиотека:

1
2
3
4
5
6
7
8
9
10
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;

$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.

Использование метаданных групп из компонента Сериализатор, предоставляет информацию о списке. Этот экстрактор не регистрируется автоматически в сервисе property_info в фреймворке Symfony:

1
2
3
4
5
6
7
8
9
10
11
12
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;

$serializerClassMetadataFactory = new ClassMetadataFactory(
    new AnnotationLoader(new AnnotationReader)
);
$serializerExtractor = new SerializerExtractor($serializerClassMetadataFactory);

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

Если serializer_groups установлена как null, метаданные групп сериалиазции не будут проверены, но вы получите только свойства, которые рассматриваются компонентом Serializer (что примечательно, аннотация @Ignore принимается во внимание).

DoctrineExtractor

Note

Этот экстрактор зависит от библиотек symfony/doctrine-bridge и doctrine/orm.

Использование данных отображения сущности из Doctrine ORM, DoctrineExtractor предоставляет информацию о типе и списке. Этот экстрактор не регистрируется автоматически сервисом property_info в фреймворке Symfony:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor;

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

// Информация о списке.
$doctrineExtractor->getProperties($class);
// Информация о типе.
$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 и PropertyInitializableExtractorInterface.

Если вы включили компонент PropertyInfo и FrameworkBundle, то вы можете автоматически регистрировать ваш экстрактор с помощью сервиса property_info, определяя его в качестве сервиса с одним или несколькими следующими тегами:

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