2010-06-24 11 views
6

Wykonałem kilka testów (aby zastąpić stary kod) metodą magiczną __invoke i nie jestem pewien czy to błąd, czy nie:PHP5.3: "Wywołanie nieokreślonej metody" błąd podczas wywoływania wywołania ze zmiennej klasy

Pozwala Załóżmy, że mamy klasę:

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

poniższych jest możliwe i działa bez problemu:

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

jednak jeśli chcę mieć inną klasę do przechowywania instancji tego obiektu , to nie działa:

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. 
    } 
} 

Błąd występuje, gdy staramy się go nazwać jak:

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

wiem, że „rozwiązanie” może być mieć funkcję wewnątrz klasy test (o nazwie k), aby "przekazać dalej" połączenie za pomocą funkcji call_user_func_array, ale to nie jest eleganckie.

Potrzebuję zachować tę instancję wewnątrz wspólnej klasy (dla celów projektowych) i móc wywoływać ją jako funkcję z innych klas ... jakiejkolwiek sugestii?

Aktualizacja:

znalazłem coś ciekawego (przynajmniej dla moich celów):

Jeśli przypisujemy "class zmienną" do zmiennej lokalnej to działa:

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

Proszę podać pełny przykład kodu, który pokazuje Twój problem. Próbka kodu, o której mówisz, działa, nie działa, a próbka kodu, którą wypowiadasz, sprawia, że ​​problem działa. – Sjoerd

+0

Tak, przepraszam, moja zła ... Aktualizuję. Sjoerd: Czy ten przykład pracował dla ciebie? dziwne: S – lepe

Odpowiedz

5

kiedy do $test->k(), PHP uważa, że ​​wywołujesz metodę na instancji $test. Ponieważ nie ma metody o nazwie k(), PHP zgłasza wyjątek. Próbujesz zrobić, aby PHP zwróciło publiczną właściwość k i wywołało to, ale aby to zrobić, musisz najpierw przypisać k do zmiennej. To kwestia dereferencji.

Można dodać magiczne __call metodę klasy Test aby sprawdzić, czy istnieje właściwość z zwanego nazwy metody i powołać się, że zamiast choć:

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

zostawiam dodanie argumentów do wywołania do Ciebie . Możesz również sprawdzić, czy właściwość is_callable.

Ale tak czy inaczej, to można zrobić

$test->k(); 
+0

Pisaliśmy w tym samym czasie ... Tak, może to mogłoby pomóc ... Jeśli nie znajdę żadnej lepszej alternatywy, zaznaczę twoją odpowiedź jako dobrą. – lepe

6

PHP myśli chcesz wywołać metodę na przykład K $ t kiedy zrobić:

$t->k(4, 5) 

która jest całkowicie uzasadnione. Można użyć zmiennej pośredniej, aby zadzwonić do obiektu:

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

Zobacz także bug #50029, który opisuje swój problem.

+0

+1 za znalezienie błędu – Gordon

+0

(+1). Teraz staje się dla mnie jasne. Dziękuję za link. – lepe

2

Nie można użyć składni metody (jak $ foo-> bar()) do wywoływania zamknięć lub obiektów za pomocą __invoke, ponieważ silnik zawsze myśli, że jest to wywołanie metody. Możesz zasymulować to przez __call:

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

ale nie zadziała tak jak jest.

Powiązane problemy