Je voudrais pouvoir appeler une fermeture que j'attribue directement à la propriété d'un objet sans réaffecter la fermeture à une variable puis l'appeler. Est-ce possible?
Le code ci-dessous ne fonctionne pas et provoque Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
php
object
properties
closures
Kendall Hopkins
la source
la source
Réponses:
Depuis PHP7, vous pouvez faire
ou utilisez Closure :: call () , bien que cela ne fonctionne pas sur un
StdClass
.Avant PHP7, vous deviez implémenter la
__call
méthode magique pour intercepter l'appel et invoquer le rappel (ce qui n'est pas possible pourStdClass
bien sûr, car vous ne pouvez pas ajouter la__call
méthode)Notez que vous ne pouvez pas faire
dans le
__call
corps, car cela se déclencherait__call
dans une boucle infinie.la source
Vous pouvez le faire en appelant __invoke sur la fermeture, car c'est la méthode magique que les objets utilisent pour se comporter comme des fonctions:
Bien sûr, cela ne fonctionnera pas si le rappel est un tableau ou une chaîne (qui peuvent également être des rappels valides en PHP) - juste pour les fermetures et autres objets avec le comportement __invoke.
la source
call_user_func($obj->callback)
n'est pas si mal.call_user_func
fonctionne aussi avec des cordes et ce n'est pas toujours pratique$obj->callback->__invoke();
quand on s'attend à ce que ce soit le cas$obj->callback()
. C'est juste une question de cohérence.$obj->callback instanceof \Closure
.À partir de PHP 7, vous pouvez effectuer les opérations suivantes:
la source
Depuis PHP 7, une fermeture peut être appelée en utilisant la
call()
méthode:Puisque PHP 7 est également possible d'exécuter des opérations sur des
(...)
expressions arbitraires (comme expliqué par Korikulum ):Les autres approches courantes de PHP 5 sont:
en utilisant la méthode magique
__invoke()
(comme expliqué par Brilliand )en utilisant la
call_user_func()
fonctionutilisation d'une variable intermédiaire dans une expression
Chaque voie a ses avantages et ses inconvénients, mais la solution la plus radicale et la plus définitive reste celle présentée par Gordon .
la source
Il semble possible d'utiliser
call_user_func()
.pas élégant, cependant ... Ce que @Gordon dit est probablement la seule voie à suivre.
la source
Eh bien, si vous insistez vraiment . Une autre solution de contournement serait:
Mais ce n'est pas la meilleure syntaxe.
Cependant, l'analyseur PHP traite toujours
T_OBJECT_OPERATOR
,IDENTIFIER
,(
comme appel de méthode. Il ne semble y avoir aucune solution de contournement pour->
contourner la table de méthodes et accéder aux attributs à la place.la source
Je sais que c'est vieux, mais je pense que Traits gère bien ce problème si vous utilisez PHP 5.4+
Tout d'abord, créez un trait qui rend les propriétés appelables:
Ensuite, vous pouvez utiliser ce trait dans vos classes:
Désormais, vous pouvez définir des propriétés via des fonctions anonymes et les appeler directement:
la source
eh bien, il faut bien comprendre que stocker la fermeture dans une variable, et appeler la variable est en fait (bizarrement) plus rapide, en fonction du montant de l'appel, ça devient pas mal, avec xdebug (donc mesure très précise), on parle 1,5 (le facteur, en utilisant une variable, au lieu d'appeler directement __invoke. Donc à la place, stockez simplement la fermeture dans une variable et appelez-la.
la source
Actualisé:
PHP> = 7:
PHP> = 5.4:
la source
Call to undefined method AnyObject::callback()
(La classe AnyObject existe, bien sûr.)Voici une autre alternative basée sur la réponse acceptée mais en étendant directement stdClass:
Exemple d'utilisation:
Vous êtes probablement mieux d'utiliser
call_user_func
ou__invoke
cependant.la source
Si vous utilisez PHP 5.4 ou supérieur, vous pouvez lier un appelable à la portée de votre objet pour invoquer un comportement personnalisé. Par exemple, si vous devez configurer la configuration suivante.
Et vous travailliez sur une classe comme ça ...
Vous pouvez exécuter votre propre logique comme si vous opériez dans le cadre de votre objet
la source
Je note que cela fonctionne en PHP5.5
Permet de créer une collection de fermetures psuedo-object.
la source