75 votes

Comment appeler une fermeture qui est une variable de classe ?

class MyClass {
  var $lambda;
  function __construct() {
    $this->lambda = function() {echo 'hello world';};
    // no errors here, so I assume that this is legal
  }
}

$myInstance = new MyClass();
$myInstance->lambda();
//Fatal error: Call to undefined method MyClass::lambda()

Quelle est donc la syntaxe correcte pour atteindre les variables de classe ?

187voto

arnaud576875 Points 35281

En PHP, les méthodes et les propriétés sont dans un espace de noms séparé (vous pouvez avoir une méthode et une propriété avec le même nom), et si vous accédez à une propriété ou à une méthode dépend de la syntaxe que vous utilisez pour le faire.

$expr->something() est un appel de méthode, donc PHP va chercher something dans la liste des méthodes de la classe.

$expr->something est une récupération de propriété, donc PHP va chercher something dans la liste des propriétés de la classe.

$myInstance->lambda(); est interprété comme un appel de méthode, donc PHP recherche une méthode nommée lambda dans votre classe, mais cette méthode n'existe pas (d'où l'indication Appel à une méthode non définie erreur).

Vous devez donc utiliser le récupérer la propriété pour récupérer le lambda, et ensuite l'appeler.

  • Depuis PHP 7.0, vous pouvez le faire avec ($obj->lambda)() :

    ($obj->lambda)();

    Les parenthèses permettent à PHP d'interpréter ($obj->lambda) como récupère la propriété nommée lambda . Alors, () appelle le résultat de la recherche de la propriété.

  • ou vous pouvez le faire avec ->lambda->__invoke() :

    $myInstance = new MyClass();
    $myInstance->lambda->__invoke();

    __invoke est l'un des Les méthodes magiques de PHP . Lorsqu'un objet implémente cette méthode, il devient invocable : il peut être appelé à l'aide de la commande $var() syntaxe. Les fonctions anonymes sont des instances de Closure qui met en œuvre __invoke .

  • Ou l'assigner à une variable locale :

    $lambda = $myInstance->lambda;
    $lambda();
  • Ou l'appeler en utilisant call_user_func :

    call_user_func($myInstance->lambda);

    call_user_func peut appeler n'importe quel callable y compris les fonctions anonymes.

  • Alternativement, s'il s'agit d'un modèle commun dans votre code, vous pouvez mettre en place un fichier __call pour transférer les appels vers votre lambda :

    class MyClass
    {
        private $lambda;
    
        public function __construct()
        {
            $this->lambda = function() {
                echo "Hello world!\n";
            };
        }
    
        public function __call($name, $args)
        {
            return call_user_func_array($this->$name, $args);
        }
    }

    Maintenant ça marche :

    $myInstance = new MyClass();
    $myInstance->lambda();

    Depuis PHP 5.4, vous pouvez même le faire dans un trait :

    trait LambdasAsMethods
    {
        public function __call($name, $args)
        {
            return call_user_func_array($this->$name, $args);
        }
    }
    
    class MyClass
    {
        use LambdasAsMethods;
    
        private $lambda;
    
        public function __construct()
        {
            $this->lambda = function() {
                echo "Hello World!\n";
            };
        }
    }
    
    $myInstance = new MyClass();
    $myInstance->lambda();

2voto

akDeveloper Points 341

Vous pouvez également appeler votre fonction lambda sans modifier quelque chose dans votre classe, en utilisant ReflectionFunction.

$myInstance = new MyClass();
$lambda = new ReflectionFunction($myInstance->lambda);
$lambda->invoke();

ou si vous devez passer des arguments, alors

$args = array('arg'=>'value');
$lambda->invokeArgs($args);

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