Problém s __call

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Vyki
Člen | 388
+
0
-

Zdravím, narazil jsem na zvláštní chování magické metody __call tříd, které dědí od třídy Object. Pokud mám:

<?php
class MojeKomponenta extends Control
{
    public function  __call($name, $arguments)
    {
        if(preg_match(('/^catch(\w+)*$/'), $name, $match))
        {
            $name = strtolower($match[1]);
        }
	parent::__call($name, $arguments);
    }

    public function test()
    {
      echo 1;
    }
}
?>

Pokud spustím s catchTest laděnka se zastaví na řádku s parent::__call($name, $arguments) a vypíše MemberAccessException Call to undefined method MojeKomponenta::test(). Neřešil bych tu k čemu to používám, spíše jsem to jenom zkoušel, ale přijde mi divné, že mě to upozorňuje na neexistující metodu, která ve skutečnosti existuje. Je to očekávané chování? Díky za radu.

Editoval Vyki (8. 3. 2010 23:16)

Ondřej Mirtes
Člen | 1536
+
0
-

A copak ta metoda v rodiči existuje? :) Podle mě je to naprosto správné chování, jaké jiné chování by sis představoval?

Ty ve své metodě __call definuješ, co se má stát, pokud někdo zavolá metodu catch*. Jak bys tam chtěl vyjádřit možnost, že někdo zavolá, kterou ani magicky nedefinuješ v __call? Kdybys tam nevolal toho parenta, tak se nestane nic, žádná chybová hláška a uživatel (tvojí třídy) se nic nedozví.

Pokud chceš docílit chování, že když někdo zavolá catchTest, tak se má zavolat test(), tak pod to nastavení proměnné $name dej $this->$name().

norbe
Backer | 405
+
0
-

Ty sice upravíš hodnotu $name z catchTest na test, ale to že zavoláš parent::__call neznamená, že se bude zkoušet volat metoda daného názvu.

Pokud chceš využít __call k upravení názvu metod, musíš pak požadovanou metodu sám zavolat, tj. něco jako $this->$name().

Edit: Pozdě :-)

Editoval norbe (8. 3. 2010 23:30)

Vyki
Člen | 388
+
0
-

Ondřej Mirtes napsal(a):

A copak ta metoda v rodiči existuje? :) Podle mě je to naprosto správné chování, jaké jiné chování by sis představoval?

Jasně to beru a je to logické, ale nechápu pak tu chybovou hlášku, která mi neříká, že není definována ta metoda v rodiči. Ta hláška říká, že metoda není definována v potomkovi, kde ovšem definována ve skutečnosti je.

Vyki
Člen | 388
+
0
-

norbe napsal(a):
Pokud chceš využít __call k upravení názvu metod, musíš pak požadovanou metodu sám zavolat, tj. něco jako $this->$name().

To $this->$name() jsem také předtím zkoušel a to šlapalo v pohodě, jenom jsem myslel, zda by to přece jenom nešlo s tím __call. Dost mě zmátla ta chybová hláška.

Jod
Člen | 701
+
0
-

Skôr:

return call_user_func_array(array($this, $name), $arguments);

Editoval Jod (9. 3. 2010 15:21)