The PropertyInfo Component

CAUTION: You are browsing the documentation for Symfony 3.0 which is not maintained anymore. Consider upgrading your projects to Symfony 3.2.

The PropertyInfo Component

The PropertyInfo component allows you to get information about class properties by using different sources of metadata.

While the PropertyAccess component allows you to read and write values to/from objects and arrays, the PropertyInfo component works solely with class definitions to provide information about the data type and visibility - including via getter or setter methods - of the properties within that class.

Installation

You can install the component in two different ways:

Then, require the vendor/autoload.php file to enable the autoloading mechanism provided by Composer. Otherwise, your application won't be able to find the classes of this Symfony component.

Additional dependencies may be required for some of the extractors provided with this component.

Usage

To use this component, create a new PropertyInfoExtractor instance and provide it with a set of information extractors.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Example\Namespace\YourAwesomeCoolClass;

// a full list of extractors is shown further below
$phpDocExtractor = new PhpDocExtractor();
$reflectionExtractor = new ReflectionExtractor();

// array of PropertyListExtractorInterface
$listExtractors = array($reflectionExtractor);

// array of PropertyTypeExtractorInterface
$typeExtractors = array($phpDocExtractor, $reflectionExtractor);

// array of PropertyDescriptionExtractorInterface
$descriptionExtractors = array($phpDocExtractor);

// array of PropertyAccessExtractorInterface
$accessExtractors = array($reflectionExtractor);

$propertyInfo = new PropertyInfoExtractor(
    $listExtractors,
    $typeExtractors,
    $descriptionExtractors,
    $accessExtractors
);

// see below for more examples
$class = YourAwesomeCoolClass::class;
$properties = $propertyInfo->getProperties($class);

Extractor Ordering

The order of extractor instances within an array matters: the first non-null result will be returned. That is why you must provide each category of extractors as a separate array, even if an extractor provides information for more than one category.

For example, while the ReflectionExtractor and DoctrineExtractor both provide list and type information it is probably better that:

  • The ReflectionExtractor has priority for list information so that all properties in a class (not just mapped properties) are returned.
  • The DoctrineExtractor has priority for type information so that entity metadata is used instead of type-hinting to provide more accurate type information.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
use Symfony\Bridge\Doctrine\PropertyInfo\DoctrineExtractor;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;

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

$propertyInfo = new PropertyInfoExtractor(
    // List extractors
    array(
        $reflectionExtractor,
        $doctrineExtractor
    ),
    // Type extractors
    array(
        $doctrineExtractor,
        $reflectionExtractor
    )
);

Extractable Information

The PropertyInfoExtractor class exposes public methods to extract four types of information:

Note

Be sure to pass a class name, not an object to the extractor methods:

1
2
3
4
5
6
7
// bad! It may work, but not with all extractors
$propertyInfo->getProperties($awesomeObject);

// Good!
$propertyInfo->getProperties(get_class($awesomeObject));
$propertyInfo->getProperties('Example\Namespace\YourAwesomeClass');
$propertyInfo->getProperties(YourAwesomeClass::class);

List Information

Extractors that implement PropertyListExtractorInterface provide the list of properties that are available on a class as an array containing each property name as a string.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$properties = $propertyInfo->getProperties($class);
/*
  Example Result
  --------------
  array(3) {
    [0] => string(8) "username"
    [1] => string(8) "password"
    [2] => string(6) "active"
  }
*/

Type Information

Extractors that implement PropertyTypeExtractorInterface provide extensive data type information for a property.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$types = $propertyInfo->getTypes($class, $property);

/*
  Example Result
  --------------
  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
    }
  }
*/

See Type Objects for info about the Type class.

Description Information

Extractors that implement PropertyDescriptionExtractorInterface provide long and short descriptions from a properties annotations as strings.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$title = $propertyInfo->getShortDescription($class, $property);
/*
  Example Result
  --------------
  string(41) "This is the first line of the DocComment."
*/

$paragraph = $propertyInfo->getLongDescription($class, $property);
/*
  Example Result
  --------------
  string(79):
    These is the subsequent paragraph in the DocComment.
    It can span multiple lines.
*/

Access Information

Extractors that implement PropertyAccessExtractorInterface provide whether properties are readable or writable as booleans.

1
2
3
4
5
$propertyInfo->isReadable($class, $property);
// Example Result: bool(true)

$propertyInfo->isWritable($class, $property);
// Example Result: bool(false)

The ReflectionExtractor looks for getter/isser/setter method in addition to whether or not a property is public to determine if it's accessible. This based on how the PropertyAccess works.

Tip

The main PropertyInfoExtractor class implements all four interfaces, delegating the extraction of property information to the extractors that have been registered with it.

This means that any method available on each of the extractors is also available on the main PropertyInfoExtractor class.

Type Objects

Compared to the other extractors, type information extractors provide much more information than can be represented as simple scalar values. Because of this, type extractors return an array of Type objects for each type that the property supports.

For example, if a property supports both integer and string (via the @return int|string annotation), PropertyInfoExtractor::getTypes() will return an array containing two instances of the Type class.

Note

Most extractors will return only one Type instance. The PhpDocExtractor is currently the only extractor that returns multiple instances in the array.

Each object will provide 6 attributes, available in the 6 methods:

Type::getBuiltInType()

The Type::getBuiltinType() method will return the built-in PHP data type, which can be one of 9 possible string values: array, bool, callable, float, int, null, object, resource or string.

Constants inside the Type class, in the form Type::BUILTIN_TYPE_*, are provided for convenience.

Type::isNullable()

The Type::isNullable() method will return a boolean value indicating whether the property parameter can be set to null.

Type::getClassName()

If the built-in PHP data type is object, the Type::getClassName() method will return the fully-qualified class or interface name accepted.

Type::isCollection()

The Type::isCollection() method will return a boolean value indicating if the property parameter is a collection - a non-scalar value capable of containing other values. Currently this returns true if:

  • The built-in PHP data type is array, or
  • The mutator method the property is derived from has a prefix of add or remove (which are defined as the list of array mutator prefixes).

Type::getCollectionKeyType() & Type::getCollectionValueType()

If the property is a collection, additional type objects may be returned for both the key and value types of the collection (if the information is available), via the Type::getCollectionKeyType() and Type::getCollectionValueType() methods.

Extractors

The extraction of property information is performed by extractor classes. An extraction class can provide one or more types of property information by implementing the correct interface(s).

The PropertyInfoExtractor will iterate over the relevant extractor classes in the order they were set, call the appropriate method and return the first result that is not null.

While you can create your own extractors, the following are already available to cover most use-cases:

ReflectionExtractor

Using PHP reflection, the ReflectionExtractor provides list, type and access information from setter and accessor methods. It can also provide return and scalar types for PHP 7+.

This service is automatically registered with the property_info service in the Symfony Framework.

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

$reflectionExtractor = new ReflectionExtractor();

// List information.
$reflectionExtractor->getProperties($class);
// Type information.
$reflectionExtractor->getTypes($class, $property);
// Access information.
$reflectionExtractor->isReadable($class, $property);
$reflectionExtractor->isWritable($class, $property);

PhpDocExtractor

Note

This extractor depends on the phpdocumentor/reflection library.

Using phpDocumentor Reflection to parse property and method annotations, the PhpDocExtractor provides type and description information. This extractor is automatically registered with the property_info in the Symfony Framework if the dependent library is present.

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

$phpDocExtractor = new PhpDocExtractor();

// Type information.
$phpDocExtractor->getTypes($class, $property);
// Description information.
$phpDocExtractor->getShortDescription($class, $property);
$phpDocExtractor->getLongDescription($class, $property);

SerializerExtractor

Note

This extractor depends on the symfony/serializer library.

Using groups metadata from the Serializer component, the SerializerExtractor provides list information. This extractor is not registered automatically with the property_info service in the Symfony Framework.

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

// List information.
$serializerExtractor->getProperties($class);

DoctrineExtractor

Note

This extractor depends on the symfony/doctrine-bridge and doctrine/orm libraries.

Using entity mapping data from Doctrine ORM, the DoctrineExtractor provides list and type information. This extractor is not registered automatically with the property_info service in the Symfony Framework.

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

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

Creating Your Own Extractors

You can create your own property information extractors by creating a class that implements one or more of the following interfaces: PropertyAccessExtractorInterface, PropertyDescriptionExtractorInterface, PropertyListExtractorInterface and PropertyTypeExtractorInterface.

If you have enabled the PropertyInfo component with the FrameworkBundle, you can automatically register your extractor class with the property_info service by defining it as a service with one or more of the following tags:

  • property_info.list_extractor if it provides list information.
  • property_info.type_extractor if it provides type information.
  • property_info.description_extractor if it provides description information.
  • property_info.access_extractor if it provides access information.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.