Zavolání vyjímky v případě, kdy vše proběhlo v pořádku

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

Zdravím,

mám drobný problém s vyjímkami. Pokud mám v Presenteru:

function(){

	try {
		.
		.
		.
		$this->flashMessage("Vše proběhlo v cajku", "success");
	} catch (\Exception $ex) {
		$this->flashMessage("Chyba: " . $ex->getMessage(), "error");
	}
}

Dost často se mi stává a nevím proč, že když všechno proběhne v pořádku tak se mi vypíše „Vše proběhlo v cajku“, ale zároveň mi vyskočí hned další zpráva "Chyba: ". S tím že se jakoby spustí vyjímka ale nic v ní není. Věděl by někdo proč mi to dělá, popřípadě jak to konkretně napravit? Nechápu proč se mi zavolá když všechno proběhlo v pořádku. Díky..

Jan Suchánek
Člen | 404
+
0
-

@Blizard: Nebude to tou obecnou Exception, když se v aplikaci někde, něco, kdo ví co, nepovedlo?

Blizard
Člen | 45
+
0
-

možná že jo. Jakým způsobem to prověřím? Mám pro každý presenter vytvořit vlastní vyjímku která bude dědit od hlavní?

Je divný že i kdyby to tím bylo a někde v aplikaci byla chyba, tak by se měla vypsat v $ex->getMessage() ne? Ono to právě nevrátí vůbec nic kromě toho že se vyhodí.

jenicek napsal(a):

@Blizard: Nebude to tou obecnou Exception, když se v aplikaci někde, něco, kdo ví co, nepovedlo?

David Matějka
Moderator | 6445
+
0
-

nemas nahodou za tou prvni flashMessage jeste redirect? v nette redirect (i jina response) vyvola vyjimku. proto neni dobry chytat vyjimky pokemon stylem :)

Blizard
Člen | 45
+
0
-

mám tam redirect no. Tím pádem se našla chyba a jak se vyvarovat Pokemon style? Případně wtf :) ?

matej21 napsal(a):

nemas nahodou za tou prvni flashMessage jeste redirect? v nette redirect (i jina response) vyvola vyjimku. proto neni dobry chytat vyjimky pokemon stylem :)

David Matějka
Moderator | 6445
+
0
-

nechytej je vsechny…

minimalne tam dej:

catch(\Nette\Application\AbortException $e) {
	throw $e;
} catch(\Exception $e) {
	//.. zpracovat vyjimku
}

tim se propusti abort exception na spravny misto..

ale dej si pozor – kdyz zobrazujes jen flashmessage, tak treba v logu vubec nezjistis, ze doslo k nejake chybe. lepsi je nechat probublat genericky vyjimky az do error presenteru a chytat pouze specificke vyjimky – prikladem je treba AuthenticationException, ktera s vyvola v Authenticatoru kdyz treba uzivatel zada spatne heslo.

Blizard
Člen | 45
+
0
-

No já ty vyjímky používám tak, že mám třeba:

		try {
			// Vypíše hlášení
			$this->flashMessage('Přihlášení do administrace proběhlo v pořádku', 'success');
			// Zaznamená log
			adminLog::log("Administrátor " . $values->email . " se přihlásil do administrace.");
			// Po úspěšném přihlášení přesměrujeme na hlavní stránku administrace
			$this->redirect('Default:default');
		} catch (\Nette\Security\AuthenticationException $ex) {
			// V případě chyby ji zaznamenáme a vypíšeme
			errorLog::log($ex->getMessage());
			$this->getPresenter()->flashMessage($ex->getMessage(), "error");
			$this->redirect('this');
		}

měl jsem tam jen \Exception a dělalo mi to zase stejný bordel s tím že se to zavolalo i když to prošlo. Teď jsem tam dal výše zobrazený \Nette\Security\AuthenticationException a je to ok.

Jak to mám ale řešit v ostatních presenterech kde budu mít třeba vyjímky na přidání produktu nebo smazání produktu? Řešení že budu dávat dva catche za sebe mi nepřijde moc elegantní. Co se stane když si pro každý presenter vytvořím třídu

class ProductException extends \Exception
{
}

Bude to potom fungovat bez problémů? Proč redirecty vyvolávají vyjímky? To by mělo pouze přesměrovat ne?

matej21 napsal(a):

nechytej je vsechny…

minimalne tam dej:

catch(\Nette\Application\AbortException $e) {
	throw $e;
} catch(\Exception $e) {
	//.. zpracovat vyjimku
}

tim se propusti abort exception na spravny misto..

ale dej si pozor – kdyz zobrazujes jen flashmessage, tak treba v logu vubec nezjistis, ze doslo k nejake chybe. lepsi je nechat probublat genericky vyjimky az do error presenteru a chytat pouze specificke vyjimky – prikladem je treba AuthenticationException, ktera s vyvola v Authenticatoru kdyz treba uzivatel zada spatne heslo.

David Matějka
Moderator | 6445
+
0
-

kratce:

  • vyvolavej pouze konkretni vyjimky
  • chytej pouze konkretni vyjimky
  • chytej pouze ty druhy vyjimek, ktery jsi schopen korektne zpracovat

ProductException – skoro ok, jen je to mozna az zbytecne konkretni :) stacilo by treba ModelException, kterou bude vyvolavat modelova vrstva tvoji aplikace…

Bude to potom fungovat bez problémů? Proč redirecty vyvolávají vyjímky? To by mělo pouze přesměrovat ne?

v nette je to kapku komplikovanejsi – kdyz das redirect, tak nedojde primo k header("Location:...") a exit, nette pouziva Response, pro presmerovani konkretne RedirectResponse a vyjimku vyvola, aby doslo k ukonceni aktualniho requestu v presenteru

Jiří Nápravník
Člen | 710
+
0
-

@matej21 Jak správně řeit ten případ, když mám klasický use case. Vezmu, uložím do databáze přidám flashmessage a přesměruji. Uložení do dtb může logicky vyhodit chybu, či-li to chce odchytit vyjímku a když je chyba tu flashmessage udělat jinou a pak přesměrovat. Ale když jí odchytnu, tak já už ji nemám zalogovanou (pokud nezavolám explicitně Debugger::log). Jak se tohle správně řeší?

akadlec
Člen | 1326
+
0
-

@Jiří Nápravník: přesměrovat mimo try-catch?

Jiří Nápravník
Člen | 710
+
0
-

Asi jsme se nepochopili, přesměrovávám mimo try – catch – nicméně já chci docílit toho, že vyjímku odchytnu, dám uživateli tedy zprávu, že se to nepovedlo. Ale zároveň chci mít zalogovanou tu chybu někde. Jde to řešit nějak inteligentněji než volat Debugger::log?

David Matějka
Moderator | 6445
+
0
-

pokud je ta vyjimka obecna a neocekavana, tak bych ji nechal proklouznout na error presenter. pokud ji vsak chces zpracovat sam, tak musis pouzit Debugger::log

Jiří Nápravník
Člen | 710
+
0
-

V mem pripade jde hlavne o vyjimky, kdy neco ukladam do databaze v modelovych třídách a odyhtávám an úrovni presenteru, pokud odchytim vyjimku, tak chci informovat, ze se neuložilo. Je otázk a jestl itenhle případ opravdu neponechat na ErrorPresenter. ale na stranu druhou zase pro uživatle může ýt apliakce bez problému fungovat, jen nebude fungovat jedna věc a jeho to hodí do errorpresenteru a může to vyvodit jako průšvih a zavře okno. Nevím co je lepší, jak to řešíte vy?

Aurielle
Člen | 1281
+
0
-

Pokud si výjimku zachytáváš a zpracováváš sám, musíš ji i sám zalogovat. Není možné nechat aplikaci běžet dál třeba s vypsáním nějaké chybové hlášky a potom spustit „část“ Debuggeru automaticky, což by ti tu výjimku zalogovalo. Explicitní volání Debugger::log() je tudíž potřeba (stejně tak si výjimku můžeš zalogovat někam jinam a Debugger vůbec nepoužít).