2009-10-01 6 views
14

Le projet sur lequel je travaille contient quelque chose comme un wrapper pour call_user_func (_array) qui effectue des vérifications avant l'exécution. L'une de ces vérifications est method_exists (Dans le cas le premier argument fourni est une instance d'une classe et le second est un nom de méthode) L'autre is_callable. La fonction lèvera une exception si l'une de ces vérifications échoue. Mon code contient un tableau avec des noms de fonctions (setFoo, setBar, etc.) et la fonction php magic pour surcharger (__call) qui gère le réglage, le remplacement et la suppression de certaines variables (mieux certains éléments du tableau).PHP __call vs method_exists

Le problème: method_exists retournera false si la fonction n'est pas définie.

Est-ce que j'ai une chance d'obtenir un vrai si la fonction __call gère correctement la requête?

+0

Grande question, je vais jouer avec cela. –

+0

Ce qui est nécessaire est une autre "méthode magique" __canCall ou quelque chose ... –

+1

is_callable() fonctionne avec des instances de classes. Je ne vois pas pourquoi vous utilisez method_exists() du tout. is_callable() fait tout ce que method_exists() fait et en plus il fonctionne avec __call(). – dave1010

Répondre

4

method_exists essaie deux choses:

  • recherches pour le nom de la méthode dans la table fonction de la classe. Ce sont les méthodes de type function foo() {}.
  • Vérifie si la classe (le code C) a une fonction (code C) get_method() et si elle l'invoque pour laisser l'implémentation de la classe décider.

Vous auriez besoin de ce dernier. Mais cette get_method() n'est pas "étendue" au code de script php, c'est-à-dire qu'il n'y a aucun moyen de laisser get_method() appeler un code de script php défini par l'utilisateur (et que retournerait ce code php?).

Donc la réponse à ma meilleure connaissance est: Non, ce n'est pas possible (encore?).

La mise en œuvre de ZEND_FUNCTION(method_exists) peut être trouvée dans zend/zend_builtin_functions.c et je pense que c'est assez lisible même si vous ne connaissez pas C mais PHP.

5

Jetez un oeil à is_callable().

Mais non, si la méthode __call() ne gère que certains noms, alors vous aurez besoin d'un autre moyen de vérifier si l'appel aboutira.

Puis-je suggérer une interface avec la méthode canCall($function), ou quelque chose? Ensuite, vérifiez si la classe implémente l'interface. Si ce n'est pas le cas, utilisez simplement is_callable().

+2

is_callable() renvoie automatiquement la valeur true si __call() est défini, ce qui rend is_callable() indéterminée (car elle ne vérifie pas que __call() satisfait la requête) –

8

__call gère les appels à des méthodes qui n'existent pas. method_exists est une méthode d'introspection qui vérifie l'existence d'une méthode.

Comment déterminer __call pour gérer une méthode? Je pense que vous devez lancer une exception manuellement dans __call si ne gère pas votre demande et attraper l'exception dans le code qui sinon utiliserait method_exists. BadMethodCallException existe à cet effet.

+1

Il semble que '__call' n'a pas la notion de" failing ", donc ressemble à jeter une 'NotImplementedException' (ou similaire) dans la méthode __call serait le moyen de le faire. –

1

Je serais tenté d'utiliser peut-être method_exists dans votre fonction __call et throw un Exception en cas d'échec et envelopper le tout dans un trycatch bloc au lieu d'utiliser la fonction is_callable.

1

Si vous êtes vraiment sûr que _call a toujours une chute en arrière, vous pouvez le faire:

if (method_exists($this, $method_name) || method_exists($this, '__call')) { 
    // Call of the method 
}