14 votes

PHP transforme "Call to a member function on a non-object" en exception

Lorsque j'exécute les étapes de "Behat", la fonction Gestionnaire d'erreurs Behat transforme les erreurs "Trying to get property of non-object" en exceptions.

Cela est très utile, car l'étape est marquée comme ayant échoué, ce qui permet au test de se poursuivre avec le scénario suivant.

Cependant, les erreurs "Call to a member function on a non-object" sont fatales et interrompent immédiatement l'exécution du test (y compris l'interruption de l'écriture des résultats au format xml). Ce n'est pas utile.

Mes questions sont les suivantes :

  1. Quelle est la différence entre ces deux erreurs ? S'agit-il de "niveaux d'erreur" différents ? Où cela est-il documenté ? J'ai cherché sur le site de PHP et sur Google, et je n'ai pas trouvé la référence canonique, juste beaucoup de questions sur le débogage des instances spécifiques de chaque erreur.

  2. Existe-t-il un moyen de convertir cette dernière erreur en exception, au lieu d'arrêter complètement le script ? Il ne me semble pas que le déréférencement de " null " avec " -> "est une erreur qui "ne peut pas être récupérée, comme un problème d'allocation de mémoire".

Mise à jour :

Il semble qu'il s'agisse d'un problème connu avec PHP. Voir :

  • #51882 L'appel d'une fonction membre à un non-objet doit déclencher une exception
  • #46601 E_RECOVERABLE_ERROR pour "Call to a member function on a non-object" (Appel à une fonction membre sur un non-objet)
  • #51848 Les erreurs d'appel de méthode non liées à un objet doivent pouvoir être rattrapées avec set_error_handler()
  • #63538 "L'appel à une fonction non définie devrait être rattrapable.

Certains disent que c'est "par conception", mais je pense que c'est juste un artefact des niveaux d'erreur qui ont été définis avant que les objets ne soient ajoutés à PHP. Dans un langage non-OO, appeler une fonction inexistante est une erreur sérieuse, et je peux voir comment elle pourrait être décrite comme "fatale" ou "non récupérable" (bien que, dans un langage non-OO où les fonctions peuvent être définies à la volée, même cela semble exagérément pessimiste). De nos jours, maintenant qu'il est possible de faire " $a->f() "sur n'importe quel vieux $a il est beaucoup plus probable que " f "peut ne pas exister, et il semble que cela ne devrait pas être une erreur fatale (cf. Java où cela serait une NullPointerException).

Je suppose que cela m'amène à une nouvelle question :

_ 3. Comment pourriez-vous patcher PHP pour rendre les erreurs "Call to a member function on a non-object" non fatales, sans casser massivement la compatibilité ascendante, et quelles mesures pourriez-vous prendre pour maximiser la probabilité que ce patch soit accepté dans PHP ?

Mise à jour 2 re Parcheando PHP :

Il existe un soutien limité sur la liste de diffusion PHP internals pour avoir effectué cette correction. Il ne me reste plus qu'à écrire un patch pour corriger cela et créer un RFC.

4voto

Hugo Delsing Points 7530

Le problème est que l'on peut déclarer les propriétés d'un objet dynamiques, mais que l'on ne peut pas déclarer une méthode dynamique. Ainsi, si vous essayez d'appeler une méthode sur un objet non dynamique, vous obtenez une erreur fatale car PHP n'a pas pu déterminer que la fonction existait.

Vérifier ce codepad pour obtenir des résultats simples avec des numéros d'erreur.

Maintenant, regardez attentivement la partie concernant la propriété "Set and acces unset" (définir et accéder à la propriété non définie). Vous pouvez voir que PHP affiche un message disant "Creating default object from empty value" (Création d'un objet par défaut à partir d'une valeur vide). Ainsi, si une classe n'existe pas, PHP la créera pour vous. La même chose se produit lorsque vous utilisez le typecasting, voir typage d'objets

Vous pouvez donc accéder à une propriété d'un non-objet, car cette propriété sera recherchée dans un objet par défaut créé de manière dynamique. Mais si vous accédez à une méthode, cet objet par défaut ne possède toujours pas cette méthode.

C'est pourquoi une propriété renvoie une erreur de niveau 8 et une méthode une erreur de niveau 1 (voir niveaux d'erreur ). Et comme il renvoie une erreur fatale de niveau 1, vous ne pouvez pas continuer après ce processus.

3voto

Rich Points 1870

Ce problème a été corrigé dans PHP 7 :

En PHP 7+, ce code est maintenant lancé, au lieu de provoquer une erreur fatale irrécupérable.

0voto

SDC Points 7176

J'ai de bonnes nouvelles pour vous : Il existe une bibliothèque PHP appelée Exceptions d'erreur qui transforme toutes les erreurs PHP en exceptions rattrapables.

Il s'agit d'un changement assez radical dans la façon dont les choses fonctionnent, mais il est clair que vous n'êtes pas le seul à vouloir le faire.

La librairie est écrite par Anthony Ferrara, qui est l'un des principaux développeurs de PHP, vous pouvez donc être sûr qu'il sait ce qu'il fait, mais au cas où vous voudriez le faire vous-même, elle se branche sur PHP en utilisant la fonction set_error_handler() fonction ; si vous voulez piéger les erreurs de PHP, voici comment faire.

J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X