Fatal error: Call to a member function getService()

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

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

HosipLan napsal(a):

Nejsnadnější bude asi nechat si vyrobit $context od Configuratoru

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 $container v 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.