2017-09-11 59 views
3

來自PHP的ReflectionMethod實例(http://php.net/manual/en/class.reflectionmethod.php)具有返回方法註釋的getDocComment方法。這工作正常,除非你使用反序列化的對象。PHP反編譯後的Doc文檔註釋

$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對象已正確定義文檔註釋,是否有任何測試方法?我的意思是,我不在乎在serialize/unserialize之後獲得註釋,但我想檢查是否調用getDocComment是安全的。


編輯:根據他的意見錯誤處理+備用,我改寫了Q.

的回答,我有思考的一些簡單的緩存(ReflectionMethod對象數組)。在我使用該緩存中的項目之前,我希望能夠正確處理它。我不想處理錯誤,我想「預測錯誤」。太棒了,就像hasDocComment方法不會產生任何錯誤,但在任何ReflectionMethod對象狀態中只返回true/false。

+0

不會getDocComment返回false它不存在? – Erik

+0

@Erik是的,它會 - 看代碼的第一部分 – Jarda

回答

1

序列化反射對象的一般方法是錯誤的。目前存在一個PHP錯誤報告,但它已經被設置爲「無關」:

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')); 
+0

我認爲(指出它的+1),但這不是我的問題的答案。我想知道如何檢查指出的方法是否會失敗。或者,根據您的筆記進行修改,如果對象與其課程之間存在正確的連接。我可以以某種方式獲取該信息嗎? – Jarda

+0

我添加了一個代碼示例,您應該做什麼 –

+0

僅序列化名稱不會幫助我,因爲我使用某些數據序列化對象,並將其用作反射的源對象...它是某個動態過程的一部分。 ..我不需要任何繞過,我需要檢查對象和其反射之間的引用 – Jarda

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(); 
} 

Demo

而且因爲你仍然可以從畸形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(); 
} 

Demo

+0

不錯的答案,但仍然沒有回答我的問題...看到上面的編輯 – Jarda