Vlastní exception handler do laděnky

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

Zdravím,

chtěl bych se zeptat, zda existuje nějaká možnost, jak upřesnit zpracování výjimek laděnkou.

Nechávám si výjimky probublávat do presenterů a mám tedy skoro ve všech metodách bloky zachytávání a zpracování výjimek. Jde mi o to, že na některé druhy výjimek reaguji pouze zobrazením zprávy, jiné se zprávou loguji a další nechávám probublat až do laděnky. Rád bych se těchto bloků z presenterů zbavil, když máme tu laděnku, takže se chci zeptat, jestli lze rozšířit laděnku tak, aby nereagovala na všechny výjimky v production mode error 500, ale třeba jen výpisem flashMessage.

Představoval bych si to tak, že bych zaregistroval do laděnky typ výjimky s callback funkcí, která se zavolá pro zpracování výjimky.

Díky za odpověď :)

Editoval darthcz (4. 2. 2013 8:45)

Filip Procházka
Moderator | 4668
+
0
-

To ale s laděnkou vůbec nesouvisí. Laděnka je jenom poslední záchrana, kdyby se všechno pokazilo, tak aby jsi se o tom dozvěděl. To je na tvé aplikaci aby tyhle chyby ošetřovala.

Můžeš si to ovšem ulehčit, například takto

class BasePresenter extends Nette\Application\UI\Presenter
{
	public $onException = array();

	/** Potřebujeme měnit chování, takže nette eventy nepoužijeme */
	public function onException(\Exception $e)
	{
		foreach ($this->onException as $handler) {
			if (callback($handler)->invoke($e, $this) === TRUE) {
				return; // výjimka zpracována
			}
		}

		// nikdo ji nechtěl :(
		throw $e;
	}

potom si zaregistruješ (klidně třeba v BasePresenter::startup()) obecné handlery

$this->onException[] = function (\Exception $e, Presenter $presenter) {
	if ($e instanceof Nette\Application\AbortException) {
		throw $e; // ukončení presenteru vždy vyhodit
	}
};
$this->onException[] = function (\Exception $e, Presenter $presenter) {
	if ($e instanceof MySpecialError) {
		$presenter->flashMessage("Nastala speciální chyba");
		return TRUE;
	}
};

Když budeš z presenteru volat věci, které můžou skončit laděnkou, tak je hezky obalíš

try {
	$this->model->operation();

} catch (\Exception $e) {
	$this->onException($e);
}

Osobně tohle harakiri považuji za naprosto zbytečné. Nejlepší je psát poctivě try {} catch () {}. Byť můžeš podlehnout dojmu, že se upíšeš, rozhodně se to vždy vyplatí.

darthcz
Člen | 113
+
0
-

Díky za odpověď. Chtěl jsem se zbavit právě těch try-catch bloků v presenteru, které v tvém řešení stejně musím psát, takže u toho zůstanu. Momentálně mám místo onException metodu processException, která porovnává druh instance výjimky místo callbacku.

Zdálo se mi fajn přenést odpovědnost za zpracování výjimek právě na nějaký další objekt, o který bych se nemusel starat, což mi přišlo, že laděnka hezky splňuje. Stačilo by jen přidat různá chování na různé výjimky. Je ale fakt, že pro tento účel vytvořena nebyla. A bylo by to asi trochu ,,magic", jelikož by nikdo další nevěděl, kde se ty výjimky odchytávají, pokud by nebyl nějaký standard zachytávat výjimky presenteru v nějaký speciální třídě.