TypeInfo 组件
TypeInfo 组件从 PHP 元素(如属性、参数和返回类型)中提取类型信息。
此组件提供:
- 强大的
Type
定义,可以处理联合类型、交叉类型和泛型(并且可以在未来扩展以支持更多类型); - 一种从 PHP 元素(如属性、方法参数、返回类型和原始字符串)获取类型的方法。
安装
1
$ composer require symfony/type-info
注意
如果在 Symfony 应用程序外部安装此组件,则必须在代码中引入 vendor/autoload.php
文件,以启用 Composer 提供的类自动加载机制。阅读这篇文章以了解更多详情。
用法
此组件为您提供一个 Type 对象,该对象表示您构建或请求解析的任何内容的 PHP 类型。
有两种方法可以使用此组件。第一种是使用 Type 静态方法手动创建类型,如下所示:
1 2 3 4 5 6 7 8 9 10
use Symfony\Component\TypeInfo\Type;
Type::int();
Type::nullable(Type::string());
Type::generic(Type::object(Collection::class), Type::int());
Type::list(Type::bool());
Type::intersection(Type::object(\Stringable::class), Type::object(\Iterator::class));
// Many others are available and can be
// found in Symfony\Component\TypeInfo\TypeFactoryTrait
解析器
使用此组件的第二种方法是使用 TypeInfo
基于反射或简单字符串解析类型。此方法专为需要简单方法来描述类或任何具有类型的库而设计:
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
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();
// Then resolve types for any subject
$typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id')); // returns an "int" Type instance
$typeResolver->resolve('bool'); // returns a "bool" Type instance
// Types can be instantiated thanks to static factories
$type = Type::list(Type::nullable(Type::bool()));
// Type instances have several helper methods
// for collections, it returns the type of the item used as the key;
// in this example, the collection is a list, so it returns an "int" Type instance
$keyType = $type->getCollectionKeyType();
// you can chain the utility methods (e.g. to introspect the values of the collection)
// the following code will return true
$isValueNullable = $type->getCollectionValueType()->isNullable();
这些调用中的每一个都将返回一个 Type
实例,该实例对应于使用的静态方法。您还可以从字符串解析类型(如上一个示例的 bool
参数所示):
PHPDoc 解析
在许多情况下,您可能没有完全类型化的属性,或者可能需要由高级 PHPDoc 提供的更精确的类型定义。为了实现这一点,您可以使用基于 PHPDoc 注解的字符串解析器。
首先,运行命令 composer require phpstan/phpdoc-parser
以安装字符串解析所需的 PHP 包。然后,按照以下步骤操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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, 'tags')); // returns a collection with "int" as key and "string" as values Type
高级用法
TypeInfo 组件提供了各种方法来操作和检查类型,具体取决于您的需求。
检查简单类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// define a simple integer type
$type = Type::int();
// check if the type matches a specific identifier
$type->isIdentifiedBy(TypeIdentifier::INT); // true
$type->isIdentifiedBy(TypeIdentifier::STRING); // false
// define a union type (equivalent to PHP's int|string)
$type = Type::union(Type::string(), Type::int());
// now the second check is true because the union type contains the string type
$type->isIdentifiedBy(TypeIdentifier::INT); // true
$type->isIdentifiedBy(TypeIdentifier::STRING); // true
class DummyParent {}
class Dummy extends DummyParent implements DummyInterface {}
// define an object type
$type = Type::object(Dummy::class);
// check if the type is an object or matches a specific class
$type->isIdentifiedBy(TypeIdentifier::OBJECT); // true
$type->isIdentifiedBy(Dummy::class); // true
// check if it inherits/implements something
$type->isIdentifiedBy(DummyParent::class); // true
$type->isIdentifiedBy(DummyInterface::class); // true
使用可调用对象进行复杂检查
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
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'));
// define a callable to validate non-nullable number types
$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
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。