112 votes

L'appel de fermeture assigné à la propriété de l'objet directement

Je voudrais être en mesure d'appeler une fermeture que j'attribue à une propriété de l'objet directement, sans réaffectation des de la fermeture pour une variable, puis en l'appelant. 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();

114voto

Gordon Points 156415

Pas de. Vous auriez à mettre en œuvre la magie __call méthode pour intercepter l'appel et appeler la fonction de rappel (qui n'est pas possible pour l' StdClass bien sûr, parce que vous ne pouvez pas ajouter de l' __call méthode)

class Foo
{
    public function __call($method, $args)
    {
        if(is_callable(array($this, $method))) {
            return call_user_func_array($this->$method, $args);
        }
        // else throw exception
    }
}

$foo = new Foo;
$foo->cb = function($who) { return "Hello $who"; };
echo $foo->cb('World');

Notez que vous ne pouvez pas faire

return call_user_func_array(array($this, $method), $args);

dans l' __appelons corps, car cela déclencherait __call dans une boucle infinie.

109voto

Brilliand Points 4167

Vous pouvez le faire en appelant __invoke sur la fermeture, puisque c'est la magie de la méthode que des objets d'usage de se comporter comme des fonctions:

$obj = new stdClass();
$obj->callback = function() {
    print "HelloWorld!";
};
$obj->callback->__invoke();

Bien sûr, cela ne fonctionnera pas si le rappel est un tableau ou une chaîne de caractères (qui peuvent aussi être valable rappels en PHP) - seulement pour les fermetures et autres objets avec d' __invoquer le comportement.

7voto

mario Points 76989

Eh bien, si vous vraiment insister. Une autre solution serait:

$obj = new ArrayObject(array(),2);

$obj->callback = function() {
    print "HelloWorld!";
};

$obj['callback']();

Mais ce n'est pas la plus belle de la syntaxe.

Cependant, l'analyseur PHP traite toujours T_OBJECT_OPERATOR, IDENTIFIER, ( comme l'appel de la méthode. Il semble y avoir aucune solution de contournement pour faire -> de contournement de la table de méthodes et d'accéder aux attributs de la place.

7voto

Pekka 웃 Points 249607

Il semble être possible à l'aide d' call_user_func().

call_user_func($obj->callback);

pas très élégant, mais.... Ce que @Gordon dit qu'il est probablement la seule façon d'aller.

7voto

SteveK Points 652

Je sais que c'est vieux, mais je pense que les Traits de bien gérer ce problème si vous utilisez PHP 5.4+

Tout d'abord, créez un trait qui fait des propriétés appelable:

trait CallableProperty {
    public function __call($method, $args) {
        if (property_exists($this, $method) && is_callable($this->$method)) {
            return call_user_func_array($this->$method, $args);
        }
    }
}

Ensuite, vous pouvez utiliser ce trait de caractère dans vos classes:

class CallableStdClass extends stdClass {
    use CallableProperty;
}

Maintenant, vous pouvez définir les propriétés via les fonctions anonymes et les contacter directement:

$foo = new CallableStdClass();
$foo->add = function ($a, $b) { return $a + $b; };
$foo->add(2, 2); // 4

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