2010-06-24 26 views
6

He estado haciendo algunas pruebas (para reemplazar el código anterior) con el método __invoke magic y no estoy seguro de si esto es un error o no:PHP5.3: error de "Llamar al método indefinido" al llamar a invocar desde la variable de clase

vamos a suponer que tenemos una clase:

class Calc { 
    function __invoke($a,$b){ 
     return $a*$b; 
    } 
} 

El siguiente es posible y funciona sin ningún problema:

$c = new Calc; 
$k = $c; 
echo $k(4,5); //outputs 20 

sin embargo, si quiero tener otra clase para almacenar una instancia de ese objeto , esto no funciona:

class Test { 
    public $k; 
    function __construct() { 
     $c = new Calc; 
     $this->k = $c; //Just to show a similar situation than before 
     // $this-k = new Calc; produces the same error. 
    } 
} 

El error se produce cuando tratamos de llamar así:

$t = new Test; 
echo $t->k(4,5); //Error: Call to undefined method Test::k() 

Sé que una "solución" podría ser tener una función dentro de la clase Test (llamado k) para "reenviar" la llamada usando call_user_func_array pero eso no es elegante.

Necesito mantener esa instancia dentro de una clase común (por motivos de diseño) y poder llamarla como función de otras clases ... ¿alguna sugerencia?

Actualización:

he encontrado algo interesante (al menos para mis propósitos):

Si asignamos la "variable de clase" en una variable local funciona:

$t = new Test; 
$m = $t->k; 
echo $m(4,5); 
+0

Proporcione un ejemplo de código completo que muestre su problema. La muestra de código que dices funciona no funciona y la muestra de código que dices da un problema. – Sjoerd

+0

Sí, lo siento, mi mal ... Lo actualizo. Sjoerd: ¿Ese ejemplo funcionó para ti? extraño: S – lepe

Respuesta

5

Cuando do $test->k(), PHP cree que está llamando a un método en la instancia $test. Como no hay un método llamado k(), PHP lanza una excepción. Lo que intenta hacer es hacer que PHP devuelva la propiedad pública k e invocar eso, pero para hacerlo primero tiene que asignar k a una variable. Es una cuestión de desreferenciación.

Se podría añadir el método mágico __call a su clase Test para comprobar si existe una propiedad con el llamado nombre del método e invocar que en lugar de que:

public function __call($method, $args) { 
    if(property_exists($this, $method)) { 
     $prop = $this->$method; 
     return $prop(); 
    } 
} 

dejo la adición de los argumentos de la invocación a usted . También es posible que desee comprobar si la propiedad is_callable.

Pero de todos modos, entonces usted puede hacer

$test->k(); 
+0

Publicamos al mismo tiempo ... Sí, quizás eso podría ayudar ... Si no encuentro otra alternativa mejor, marcaré su respuesta como buena. – lepe

6

PHP piensa que desea llamar a un método en la instancia k $ t cuando lo hace:

$t->k(4, 5) 

que es perfectamente razonable. Se puede utilizar una variable intermedia para llamar al objeto:

$b = $t->k; 
$b(4, 5); 

Véase también bug #50029, que describe su problema.

+0

+1 para encontrar el error – Gordon

+0

(+1). Ahora se está poniendo claro para mí. Gracias por el enlace. – lepe

2

No se puede usar la sintaxis del método (como $ foo-> bar()) para llamar cierres u objetos con __invoke, ya que el motor siempre piensa que se trata de una llamada a método. Puede simularlo a través de __call:

function __call($name, $params) { 
    if(is_callable($this->$name)) { 
    call_user_func_array($this->$name, $params); 
    } 
} 

pero no funcionaría como está.

Cuestiones relacionadas