Zavolání vyjímky v případě, kdy vše proběhlo v pořádku
- Blizard
- Člen | 45
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
@Blizard: Nebude to tou obecnou Exception, když se v aplikaci někde, něco, kdo ví co, nepovedlo?
- Blizard
- Člen | 45
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
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
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
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
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
@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ší?
- Jiří Nápravník
- Člen | 710
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
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
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
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).