Různý Error presenter pro různé moduly

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

Asi nepřicházím s ničím úplně novým, ale stejně… Pro zprovoznění stačí přidat události onRequest objektu Application následující funkci.

<?php
class Foo {
	/**
	 * @param Nette\Application\Application $app
	 * @param Nette\Application\PresenterRequest $request
	 * @return void
	 */
	public static function setErrorPresenter ($app, $request) {
		$presenter = $request->getPresenterName();
		$errorPresenter = 'Error';

		if(($pos = strrpos($presenter, ':')) !== false) {
			try {
				$errorPresenter = substr($presenter, 0, ($pos + 1)) . 'Error';
				$errorPresenterClass = $app->getPresenterLoader()->getPresenterClass($errorPresenter);

			} catch (Nette\Application\InvalidPresenterException $e) {
				$errorPresenter = 'Error';

			}
		}

		$app->errorPresenter = $errorPresenter;
	}
}
?>

Aplikace pak bude při chybě (a Application::$catchExceptions = true) automaticky spouštět, pokud existuje, presenter Error v modulu, ve kterém se nachází presenter, jenž vyhodil výjimku. Pokud používate Nette bez jmenných prostorů, stačí nahradit „Nette\Application\InvalidPresenterException“ za „InvalidPresenterException“

Filip Procházka
Moderator | 4668
+
0
-

Šikovné (až na kompatibilitu k novému Nette). Lepší řešení asi nikoho nenapadá co? :)

Editoval HosipLan (14. 6. 2011 10:12)

Jan Suchánek
Člen | 404
+
0
-

Zdravím stačí jen přepsat?

$errorPresenterClass = $app->getPresenterFactory()->getPresenterClass($errorPresenter);

Nebo je potřeba ještě něco?

hAssassin
Člen | 293
+
0
-

potvrzuji, zkusil sem si to pridat do Application a zda se ze to vali. Mam vlastni tridu Application, ktera dedi z \Nette\Application\Application:

class SiteApplication extends \Nette\Application\Application

	// ... properties a konstruktor

	public function run()
	{
		// Error presenter podle modulu
		//$this->errorPresenter = 'Error'; - neni potreba
		//$this->catchExceptions = true; - neni potreba

		$this->onRequest[] = function($app, $request) {
			$presenter = $request->presenterName;
			$errorPresenter = 'Error';

			if(($pos = strrpos($presenter, ':')) !== false) {
				try {
					$errorPresenter = substr($presenter, 0, ($pos + 1)) . 'Error';
					$errorPresenterClass = $app->presenterFactory->createPresenter($errorPresenter);
				}
				catch (Nette\Application\InvalidPresenterException $e) {
					$errorPresenter = 'Error';
				}
			}

			$app->errorPresenter = $errorPresenter;
		};


		// Vola rodice !!!
		parent::run();

		return;
	} // run()

};

Zatim to teda vali (resp. sem to zkousel) pouze pro dva hlavni moduly (admin a front). Pokud vsak by bylo vic submodulu napr v modulu admin, tak to asi bude tahat error presenter z admin modulu, ale to uz problem neni. Jo verzi nette mam version 2.0.1 released on 2012-02-29.

Kazdopadne diky za skveli napad…

EDIT: az ted sem si vsimnul, ze to je rok stare vlakno :D Ale co uz, hlavne ze to vali i v novym nette ;)

Editoval hAssassin (23. 3. 2012 20:04)

fak
Člen | 48
+
0
-

a jak tu SiteApplication vnutím při startu?

castamir
Člen | 629
+
0
-

@fak v bootstrap.php:

$container->application->onRequest[] = ...
pekelnik
Člen | 462
+
0
-

Tohle je fakt vtipný vlákno :P

castamir
Člen | 629
+
0
-

@pekelnik to máš pravdu. Dotazů na Error presenter už bylo hodně, ale nikde jsem neviděl řešení, tak jsem si řekl, že by se to někomu mohlo hodit. Neříkám, že obsah metody onRequest je ideální, jen naznačuju, kde to připojit k aplikaci…

one-two
Člen | 80
+
0
-

Mám Nette 2.1dev a nejsem schopný to dát dohromady, našel někdo řešení? Kód který je nahoře mi nefunguje, když si dumpnu $context->application tak tam sice vidim jiný errorPresenter ale zapne se stejně ten, který je v configu…

ZZromanZZ
Člen | 87
+
0
-

Mělo by fungovat to, že si injectuješ \Nette\Application\Application v BasePresenteru konkrétního modulu

/** @var \Nette\Application\Application @inject */
public $application;

A pak si ve startup() metodě přiřadíš errorPresenter odkud chceš:

$this->application->errorPresenter = "Module:Error";

Editoval ZZromanZZ (11. 7. 2013 21:19)

one-two
Člen | 80
+
0
-

ZZromanZZ napsal(a):

Mělo by fungovat to, že si injectuješ \Nette\Application\Application v BasePresenteru konkrétního modulu

to mi bohužel taky nefunguje. Buď to bere pouze ten co je v configu a pokud tenhle parametr zakomentuju, tak se spustí defaultní NetteModule\ErrorPresenter

ZZromanZZ
Člen | 87
+
0
-

To se mi nezdá. Mi to v dev verzi funguje dobře a myslím, že není důvod, proč by tobě nemělo. Máš dobře zadaný ten string(cestu) k errorPresenteru ? Mělo by to být nějak takto:

$application->errorPresenter = "Module:SubModule:SubsubModule:Presenterprefix";

Když tak nastiň tvůj strom modulů a kde máš errorPresentery a možná ti už tady pomůžem.

// edit: A je to nutno zadávat bez počáteční dvojtečky

Editoval ZZromanZZ (12. 7. 2013 11:20)

one-two
Člen | 80
+
0
-

Mám FrontModule a ApiModule, třídy App\*Module\*Presenter, pokud zavolám v presenteru $this->error() tak už to teďkon správně zobrazuje příslušnej ErrorPresenter, ale pokud tam mam nějakej například fatal error, tak to zas začne zpracovávat ten výchozí, případně ten z configu

ZZromanZZ
Člen | 87
+
0
-

Ono je pak otázka, kde se ten fatal error vyvolá(a co ho vyvolá), jestli je to nějaká syntax error, tak s tím asi bohužel nic nenaděláme. Tyhle ty errorPresentery jsou typicky pro přístupy na neexistující stránky(detaily zboží, články, atd…) a podobné „soft“ chyby.

one-two
Člen | 80
+
0
-

jj, tak aspoň ty neexistující stránky si pořešim přes to injectnutí Application, které funguje
díky za pomoc

sKopheK
Člen | 207
+
0
-

Modul se mi daří zjistit pouze u defaultního modulu, u dalších není k dispozici.