class Expense {
/**
* @var int
*/
private $id;
}
我想使用反射获取类中变量的类型提示,因为默认值为null。
答案 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()