跳到内容

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 许可协议获得许可。
目录
    版本