diff --git a/components/type_info.rst b/components/type_info.rst index bbc7d0ea8dc..18556e02972 100644 --- a/components/type_info.rst +++ b/components/type_info.rst @@ -40,12 +40,24 @@ to the :class:`Symfony\\Component\\TypeInfo\\Type` static methods as following:: // Many others are available and can be // found in Symfony\Component\TypeInfo\TypeFactoryTrait +Resolvers +~~~~~~~~~ + The second way of using the component is to use ``TypeInfo`` to resolve a type -based on reflection or a simple string:: +based on reflection or a simple string, this is aimed towards libraries that wants to +describe a class or anything that has a type easily:: use Symfony\Component\TypeInfo\Type; use Symfony\Component\TypeInfo\TypeResolver\TypeResolver; + class Dummy + { + public function __construct( + public int $id, + ) { + } + } + // Instantiate a new resolver $typeResolver = TypeResolver::create(); @@ -70,6 +82,88 @@ Each of these calls will return you a ``Type`` instance that corresponds to the static method used. You can also resolve types from a string (as shown in the ``bool`` parameter of the previous example) -.. note:: +PHPDoc parsing +~~~~~~~~~~~~~~ - To support raw string resolving, you need to install ``phpstan/phpdoc-parser`` package. +But most times you won't have clean typed properties or you want a more precise type +thank to advanced PHPDoc, to do that you would want a string resolver based on that PHPDoc. +First you will require ``phpstan/phpdoc-parser`` package from composer to support string +revolving. Then you would do as following:: + + use Symfony\Component\TypeInfo\TypeResolver\TypeResolver; + + class Dummy + { + public function __construct( + public int $id, + /** @var string[] $tags */ + public array $tags, + ) { + } + } + + $typeResolver = TypeResolver::create(); + $typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id')); // returns an "int" Type + $typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id')); // returns a collection with "int" as key and "string" as values Type + +Advanced usages +~~~~~~~~~~~~~~~ + +There is many methods to manipulate and check types depending on your needs within the TypeInfo components. + +If you need a check a simple Type:: + + // You need to check if a Type + $type = Type::int(); // with a simple int type + // You can check if a given type comply with a given identifier + $type->isIdentifiedBy(TypeIdentifier::INT); // true + $type->isIdentifiedBy(TypeIdentifier::STRING); // false + + $type = Type::union(Type::string(), Type::int()); // with an union of int and string types + // You can now see that the second check will pass to true since we have an union with a string type + $type->isIdentifiedBy(TypeIdentifier::INT); // true + $type->isIdentifiedBy(TypeIdentifier::STRING); // true + + class DummyParent {} + class Dummy extends DummyParent implements DummyInterface {} + $type = Type::object(Dummy::class); // with an object Type + // You can check is the Type is an object, or even if it's a given class + $type->isIdentifiedBy(TypeIdentifier::OBJECT); // true + $type->isIdentifiedBy(Dummy::class); // true + // Or inherits/implements something + $type->isIdentifiedBy(DummyParent::class); // true + $type->isIdentifiedBy(DummyInterface::class); // true + +Sometimes you want to check for more than one thing at a time so a callable may be better to check everything:: + + class Foo + { + private int $integer; + private string $string; + private ?float $float; + } + + $reflClass = new \ReflectionClass(Foo::class); + + $resolver = TypeResolver::create(); + $integerType = $resolver->resolve($reflClass->getProperty('integer')); + $stringType = $resolver->resolve($reflClass->getProperty('string')); + $floatType = $resolver->resolve($reflClass->getProperty('float')); + + // your callable to check whatever you need + // here we want to validate a given type is a non nullable number + $isNonNullableNumber = function (Type $type): bool { + if ($type->isNullable()) { + return false; + } + + if ($type->isIdentifiedBy(TypeIdentifier::INT) || $type->isIdentifiedBy(TypeIdentifier::FLOAT)) { + return true; + } + + return false; + }; + + $integerType->isSatisfiedBy($isNonNullableNumber); // true + $stringType->isSatisfiedBy($isNonNullableNumber); // false + $floatType->isSatisfiedBy($isNonNullableNumber); // false