php:使用反射获取变量类型提示

时间:2011-06-06 09:46:50

标签: php class reflection types

class Expense {

    /**
     * @var int
     */
    private $id;
}

我想使用反射获取类中变量的类型提示,因为默认值为null。

6 个答案:

答案 0 :(得分:15)

尝试:

<?php
class Expense {

    /**
     * @var int
     */
    private $id;
}

$refClass = new ReflectionClass('Expense');
foreach ($refClass->getProperties() as $refProperty) {
    if (preg_match('/@var\s+([^\s]+)/', $refProperty->getDocComment(), $matches)) {
        list(, $type) = $matches;
        var_dump($type);
    }
}

<强>输出

string(3) "int"

答案 1 :(得分:3)

获取完整的Docblock:

$reflection = new ReflectionProperty('Expense', 'id');

$doc = $reflection->getDocComment();

答案 2 :(得分:1)

如果事实证明PHPDoc注释丢失或不可靠,则可以键入hint类的所有属性,前提是它们具有匹配的getter

public function getClassPropertiesType(string $className): array {
    $reflectionClass = new \ReflectionClass($className);

    $reflectionProperties = $reflectionClass->getProperties();
    $properties = [];
    foreach ($reflectionProperties as $reflectionProperty) {
        $properties[] = $reflectionProperty->getName();
    }

    $methods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
    $results = [];

    foreach ($properties as $property) {
        foreach ($methods as $method) {
            // get only methods that have 0 parameter and start with 'get'
            if ($method->getNumberOfParameters() === 0 && 
                  strpos($method->getName(),'get') !== false && 
                  stripos($method->getName(), $property) !== false) {

                $results[$property] = (string)$method->getReturnType();
            }
        }
    }

    return $results;
}

从逻辑上讲,该类的每个属性应该只有一个吸气剂。

如果我转储某些类的属性:

  0 => "id"
  1 => "email"
  2 => "password"
  3 => "firstName"
  4 => "lastName"
  5 => "gender"
  6 => "position"
  7 => "isActive"
  9 => "dateEmployedFrom"
  10 => "dateEmployedTo"
  11 => "dateOfBirth"
  12 => "ssn"
  13 => "mobilePhone"
  14 => "homePhone"
  15 => "address"
  16 => "zipCode"
  17 => "city"
  18 => "country"

这是您得到的:

  "id" => "int"
  "email" => "string"
  "password" => "string"
  "firstName" => "string"
  "lastName" => "string"
  "gender" => "bool"
  "position" => "string"
  "isActive" => "bool"
  "dateEmployedFrom" => "DateTimeInterface"
  "dateEmployedTo" => "DateTimeInterface"
  "dateOfBirth" => "DateTimeInterface"
  "ssn" => "string"
  "mobilePhone" => "string"
  "homePhone" => "string"
  "address" => "string"
  "zipCode" => "string"
  "city" => "string"
  "country" => "string"

限制+解决方法

如果属性没有任何获取器,则可以开始查找setter(或以'add','is','remove'开头的方法),只要该方法的参数是类型提示的您还可以在搜索中包括私有财产 $methods = $reflectionClass->getMethods(); // no filter

在返回之前,我建议像这样展开:

        $missingProperties = array_diff_key(array_flip($properties), $results);

        if (!empty($missingProperties)) { // some properties are missing

            foreach ($missingProperties as $missingProperty => $val) {
                // get only methods that have 1 parameter and start with 'set'
                if ($method->getNumberOfParameters() === 1 && strpos($method->getName(), 'set') !== false) { 
                    $parameters = $method->getParameters();

                    // if not already in results, and parameter is required 
                    // and is a class property
                    if(!array_key_exists($parameters[0]->getName(), $results) &&
                                !$parameters[0]->isOptional() && 
                                in_array($parameters[0]->getName(), $properties, true)) {

                        $string = $parameters[0]->__toString();

                        $string = substr($string, strlen('Parameter #0 [ <required> '));
                        $pos = strpos($string, ' '); // get first space after type
                        $string = substr($string, 0, $pos); // get type

                        $results[$parameters[0]->getName()] = $string;
                    }
                }
            }
        }

当然,这不是100%防弹的,但希望能有所帮助。 :-)

最后:PHP 7.4引入了ReflectionParameter::getType 因此,您可以删除上面的字符串操作,然后编写:

                $type = $parameters[0]->getType();
                $results[$parameters[0]->getName()] = $type->__toString();

答案 3 :(得分:1)

对于PHP 7.4

$reflection = new \ReflectionProperty('className', 'propertyName');
echo $reflection->getType()->getName();

答案 4 :(得分:0)

一点警告 - PHP加速器和一些库本身(即symfony核心)在第二次运行时经常删除注释。

答案 5 :(得分:0)

您可以使用ReflectionDocBlock

安装

composer require phpdocumentor/reflection-docblock

用法:

$factory  = \phpDocumentor\Reflection\DocBlockFactory::createInstance();

$reflectionClass = new ReflectionClass(MyClass::class);
$property = $reflectionClass->getProperty('foo');

$docBlock = $factory->create($property->getDocComment());

//it returns an array, as a property might declare many types
//for example @var int|string|null
$types = $docBlock->getTagsByName('var')[0]->getType()

请参见ReflectionClassReflectionProperty的参考