2017-09-11 3 views
3

L'instance ReflectionMethod de PHP (http://php.net/manual/en/class.reflectionmethod.php) a la méthode getDocComment qui renvoie l'annotation d'une méthode. Cela fonctionne bien, sauf si vous utilisez un objet non sérialisé.PHP Doc commentaire après la désérialisation

$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 

Est-il possible de tester si l'objet ReflectionMethod a défini correctement commentaire doc? Je veux dire, je ne me soucie pas d'obtenir l'annotation après serialize/unserialize, mais je veux vérifier si l'appel getDocComment est sûr.


Edit: D'après les réponses que le traitement des erreurs de conseils + fallback, je vais reformuler ma Q.

J'ai une cache simple des reflets (tableau de ReflectionMethod objets). Jusqu'à ce que j'utilise un objet de cette cache, je me plains de vérifier son exactitude. Je ne veux pas gérer l'erreur, je veux "prédire l'erreur". Génial serait quelque chose comme hasDocComment méthode qui ne génère pas d'erreur, mais renvoie uniquement vrai/faux dans un ReflectionMethod état de l'objet.

+0

Wont getDocComment retourner false il n'existe pas? – Erik

+0

@Erik oui il va - voir la première partie du code – Jarda

Répondre

1

L'approche générale de sérialisation des objets de réflexion est incorrecte. Il existe un rapport de bogue PHP pour, mais il a été réglé sur « non pertinent »:

https://bugs.php.net/bug.php?id=70719

La raison est que vous ne pouvez pas connecter un objet de réflexion à sa classe à nouveau, parce que vous auriez à gérer les changements de code source et toutes sortes de choses. Ce que vous devez faire à la place est de sérialiser le nom de la classe et de générer un nouvel objet de réflexion à partir de cette classe, lorsque vous désérialisez.

Exemple de code:

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

Je suppose que (+1 pour le signaler), mais ce n'est pas une réponse à mon Q. Je voudrais savoir comment vérifier si la méthode indiquée échouera. Ou, modifié en fonction de votre note, s'il existe une connexion correcte entre l'objet et sa classe. Puis-je obtenir d'une façon ou d'une autre cette information? – Jarda

+0

J'ai ajouté un exemple de code ce que vous devez faire à la place –

+0

La sérialisation du nom ne m'aidera pas puisque je sérialise l'objet avec quelques données, et cela est utilisé comme objet source pour la réflexion ... Cela fait partie d'un processus dynamique. .. Je n'ai pas besoin de contourner, j'ai besoin de vérifier la référence entre l'objet et sa réflexion – Jarda

1

Si vous devez être en mesure de gérer les erreurs, vous pouvez essayer/attraper le bloc d'exécution. Depuis alt-php71-7.1.0-1 (que vous semblez utiliser), cela lancera une instance de Error au lieu de simplement un Fatal Error, ce qui vous permet de gérer les erreurs.

<?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

Et puisque vous pouvez toujours obtenir le nom de classe de la malformé Reflection exemple, vous pouvez instancier un nouveau droit dans votre bloc 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

Belle réponse, mais ne répondant toujours pas à ma question ... voir la modification ci-dessus – Jarda