2011-08-15 6 views
60
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() 

Entonces, ¿cuál es la sintaxis correcta para llegar a las variables de la clase?¿Cómo llamar a un cierre que es una variable de clase?

Respuesta

158

En PHP, los métodos y las propiedades están en un espacio de nombre separado (puede tener un método y una propiedad con el mismo nombre) y si está accediendo a una propiedad o un método depende de la sintaxis que utiliza para hacerlo .

$expr->something() es una llamada a método, por lo que PHP buscará something en la lista de métodos de la clase.

$expr->something es una búsqueda de propiedad, por lo que PHP buscará something en la lista de propiedades de la clase.

$myInstance->lambda(); se analiza como una llamada de método, por lo que PHP busca un método llamado lambda en su clase, pero no hay tal método (de ahí el La llamada al método definido error).

Así que tiene que utilizar la búsqueda de la propiedad sintaxis para recuperar el lambda, y luego llamarlo.

  • A partir de PHP 7.0, puede hacer esto con ($obj->lambda)():

    ($obj->lambda)(); 
    

    Los paréntesis se aseguran de que PHP analiza como ($obj->lambda)buscar a la propiedad llamado lambda. Luego, () llama al resultado de ir a buscar la propiedad.

  • o se puede hacer esto con ->lambda->__invoke():

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

    __invoke es uno de PHP's magic methods. Cuando un objeto implementa este método, se vuelve invocable: se puede invocar utilizando la sintaxis $var(). Las funciones anónimas son instancias de Closure, que implementa __invoke.

  • O asignarlo a una variable local:

    $lambda = $myInstance->lambda; 
    $lambda(); 
    
  • O llamarlo usando call_user_func:

    call_user_func($myInstance->lambda); 
    

    call_user_func puede llamar a cualquier callable, incluyendo funciones anónimas.

  • Alternativamente, si se trata de un patrón común en su código, se puede configurar un método __call permite desviar las llamadas a su 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); 
        } 
    } 
    

    Ahora bien, esto funciona:

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

    A partir de PHP 5.4 que incluso puede hacer que en un rasgo:

    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(); 
    
+9

explicación Bastante perfecto =) – Rudie

+0

Niza, aunque sería agradable ver '__invoke /()' 'vs. call_user_func' notas. –

+1

¡Muy buena explicación! Muy rico en ejemplos. – Ricardo

2

También puede llamar a su función lambda sin cambiar algo en su clase, utilizando ReflectionFunction.

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

o si tiene que pasar argumentos continuación

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

Esta no es la forma más corta ni la más eficiente de hacerlo. – amphetamachine

Cuestiones relacionadas