PHP中的ReflectionMethod
实例(http://php.net/manual/en/class.reflectionmethod.php)具有getDocComment
方法,该方法返回方法的注释。除非你使用反序列化的对象,否则这样做没问题。
$ref = new ReflectionClass('a');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
$ref = unserialize(serialize($ref));
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //PHP Warning: Uncaught Error: Internal error: Failed to retrieve the reflection object
有没有办法测试ReflectionMethod
对象是否正确定义了文档注释?我的意思是,我不关心在序列化/反序列化后获取注释,但我想检查调用getDocComment
是否安全。
编辑:根据建议错误处理+回退的回复,我改写了Q。
我有一些简单的反射缓存(ReflectionMethod
个对象的数组)。直到我使用该缓存中的项目,我才想知道它的正确性。我不想处理错误,我想“预测错误”。令人敬畏的是hasDocComment
方法,它不会产生任何错误,但在任何ReflectionMethod
对象状态内只返回true / false。
答案 0 :(得分:2)
序列化反射对象的一般方法是错误的。它有一个PHP Bug报告,但它被设置为"无关紧要":
https://bugs.php.net/bug.php?id=70719
原因是,您无法再将反射对象重新连接到其类,因为您必须处理源代码更改和各种内容。你应该做的是,序列化类的名称,并在反序列化时从该类生成一个新的反射对象。
代码示例:
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment'));
// serialize only the class name
$refClass = unserialize(serialize($ref->getName()));
// get a new reflection object from that class ...
$ref = new ReflectionClass($refClass);
var_dump(method_exists($ref, 'getDocComment'));
// If you want to serialize an object
$a = new A();
$a2 = unserialize(serialize($a));
$ref = new ReflectionClass(get_class($a2));
var_dump(method_exists($ref, 'getDocComment'));
答案 1 :(得分:1)
如果您需要能够处理错误,可以尝试/捕获执行块。自alt-php71-7.1.0-1(您似乎正在使用)以来,这将抛出Error
的实例,而不仅仅是Fatal Error
,这样您就可以进行错误处理。
<?php
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
// serialize only the class name
$refClass = unserialize(serialize($ref));
try {
$refClass->getDocComment();
// do your work
}
catch (Error $e) {
echo "Malformed Reflection object: ".$e->getMessage();
}
由于您仍然可以从格式错误的Reflection
实例中获取类名,因此您可以在catch
块中实例化一个新的名称:
<?php
class A { }
$ref = new ReflectionClass('A');
var_dump(method_exists($ref, 'getDocComment')); //bool(true)
var_dump($ref->getDocComment()); //bool(false)
// serialize only the class name
$refClass = unserialize(serialize($ref));
try {
$refClass->getDocComment();
}
catch (Error $e) {
$recoveredRef = new ReflectionClass($refClass->getName());
var_dump($recoveredRef);
var_dump($recoveredRef->getDocComment()); // works correctly
echo "Malformed Reflection object, but recovered: ".$e->getMessage();
}