PHP是一种弱类型的编程语言。这意味着你不必声明变量类型(比如intbool)即可在同一变量中存储不同类型的数据(比如数字或字符串)。

开发者们部分克服了这种约束,多亏了type hintsphpDoc以及,从PHP 7开始,return type declarations。不过,在一些场景下,仍然需要知道PHP的属性类型。这就是为什么Symfony新增了一个组件名为PropertyInfo

给定一个PHP类,本组件能得到它的全部属性的信息,靠的是内部检索若干metadata providers(元数据提供者),例如Doctrine ORM mapping,php Doc comments,PHP type hints,serializer metadata,等等。

请看下列Doctrine entity类,包含了不同类型的属性:

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
namespace AppBundle\Entity;
 
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @Entity
 */
class FooClass
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    public $id;
 
    /**
     * This is a date (short description).
     *
     * With a long description.
     *
     * @var \DateTime
     */
    public $foo;
 
    private $bar;
 
    public function setBar(\SplFileInfo $bar)
    {
        $this->bar = $bar;
    }
}

在使用PropertyInfo来解得信息之前,你必须创建和配置metadata提取器(ReflectionExtractorPhpDocExtractorDoctrineExtractorSerializerExtractor已经内置,但你也可以自行创建提取器)。

1
2
3
4
5
6
7
8
use Symfony\Component\PropertyInfo\PropertyInfo;
 
$propertyInfo = new PropertyInfo(
    array($reflectionExtractor),
    array($doctrineExtractor, $phpDocExtractor, $reflectionExtractor),
    array($phpDocExtractor),
    array($reflectionExtractor)
);

现在你可以像下面这样,检视每一个属性的类型:

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
32
33
34
35
36
37
38
$propertyInfo->getTypes('FooClass', 'foo');
// array(1) {
//   [0] =>
//   class Symfony\Component\PropertyInfo\Type#36 (6) {
//     private $builtinType => string(6) "object"
//     private $nullable => bool(false)
//     private $class => string(8) "DateTime"
//     private $collection => bool(false)
//     private $collectionKeyType => NULL
//     private $collectionValueType => NULL
//   }
// }
 
$propertyInfo->getTypes('FooClass', 'id');
// array(1) {
//   [0] =>
//   class Symfony\Component\PropertyInfo\Type#36 (6) {
//     private $builtinType => string(3) "int"
//     private $nullable => bool(false)
//     private $class => NULL
//     private $collection => bool(false)
//     private $collectionKeyType => NULL
//     private $collectionValueType => NULL
//   }
// }
 
$propertyInfo->getTypes('FooClass', 'bar');
// array(1) {
//   [0] =>
//   class Symfony\Component\PropertyInfo\Type#245 (6) {
//     private $builtinType => string(6) "object"
//     private $nullable => bool(false)
//     private $class => string(11) "SplFileInfo"
//     private $collection => bool(false)
//     private $collectionKeyType => NULL
//     private $collectionValueType => NULL
//   }
// }

本组件包含了其他工具以解出有用信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
$propertyInfo->getProperties('FooClass');
// ['id', 'foo', 'Bar']
 
$propertyInfo->isReadable('FooClass', 'id');   // true
$propertyInfo->isReadable('FooClass', 'bar');  // false
$propertyInfo->isWritable('FooClass', 'foo');  // true
$propertyInfo->isWritable('FooClass', 'bar');  // true
 
$propertyInfo->getShortDescription('FooClass', 'foo');
// "This is a date (short description)."
 
$propertyInfo->getLongDescription('FooClass', 'foo');
// "With a long description."