Fatal error: Call to a member function getService()

- RDPanek
 - Člen | 189
 
Ahoj, chci spustit životní cyklus presenteru:
$presenter  = new HomepagePresenter;
$request    = new PresenterRequest('Homepage', 'GET', array());
$response   = $presenter->run($request);
ale třetí řádek mi vyhazuje chybku:
Fatal error: Call to a member function getService() on a non-object in
/Volumes/htdocs/projects/libs/Nette/Application/Presenter.php on line 1250
prosel jsem si forum, ale na reseni jsem nenarazil. Díky

- Filip Procházka
 - Moderator | 4668
 
V tom případě jsi fórum procházel špatně.
Presenter závisí na předaném kontextu s určitou množinou služeb, které přímo využívá.
Nejsnadnější bude asi nechat si vyrobit $context od
Configuratoru
$configurator = new Nette\Configurator;
$container = $configurator->getContainer();
$presenter = new Presenter;
$presenter->setContext($container);
$request = new PresenterRequest('Homepage', 'GET', array());
$response = $presenter->run($request);
Je potřeba dávat bacha na Configurator a
Container. Protože Configurator je kapku ohackovaný
kvůli kompatibilitě s Environment.
Za tuhle radu se stydím, ale nejjednodušší způsob jak
$container v testech získat je
$context = Nette\Environment::getContext(). Pokud to chceš ale
udělat pořádně, pak směle do toho.
Pokud někdo má nápad, jak ho získat lépe, pak sem s ním. Testovat presentery se mi totiž zatím moc nechce.
PHPUnit sám o sobě je hromádka statických tříd, takže to půjde dost blbě…

- kravčo
 - Člen | 721
 
Možno skôr stálo za to pozrieť sa do súboru
.../Nette/Application/Presenter.php na riadok 1250…
Okrem toho nie je jasné, akú máš verziu Nette, PHP ani nič iné. Tipol by som však, že inkriminovaný riadok vyzerá nejak takto:
final public function getService($name)
{
    return $this->context->getService($name); // <-- riadok 1250
}
To čo v takom prípade potrebuješ je nastaviť prezenteru kontext, predtým ako ho spustíš:
$presenter->setContext(Nette\Environment::getContext());
Prípadne ak testovanie nejako súvisí so službami, možno budeš potrebovať vlastný mock objekt kontextu.

- Nox
 - Člen | 378
 
A proč teda ne Configurator::getContainer?
Nebo případně si dej MyTestCase::getContext/ainer (má to context X container vůbec nějakou logiku nebo je jen na zmatení nepřítele?) a do nej si klidně Environment::getContext() dej – v tom není vůbec problém, protože způsob jakým kontext získáváš je pak vyměnitelný a sám Environment ho nezískává nijak svévolně, ale přes injecnutý Container – opět flexibilní

- kravčo
 - Člen | 721
 
HosipLan napsal(a):
Nejsnadnější bude asi nechat si vyrobit
$contextodConfiguratoru
Najjednoduchšie je získať ho z Environment.
$configurator = new Nette\Configurator; $container = $configurator->getContainer(); // ...Za tuhle radu se stydím, ale nejjednodušší způsob jak
$containerv testech získat je$context = Nette\Environment::getContext(). Pokud to chceš ale udělat pořádně, pak směle do toho.
V tom prípade by si sa mal hanbiť aj za tú predošlú. Pretože
Nette\Environment::getContext() spraví presne to isté.
Treba si uvedomiť že sme v kóde testu a ak chceme mockovať, použijeme
priamo vlastný kontext a Configurator ani Environment
nám vôbec netreba:
$presenter->setContext(new MockContext);
V opačnom prípade nie je dôvod nepoužiť Environment.