Zobrazení chyby ve stránce
- Mirek
- Člen | 86
Zjistil jsem, že když zapomenu v presenteru nadefinovat proměnnou, kterou pak využívám v šabloně, tak se mi v zobrazené stránce objeví výpis této chyby – Notice: Undefined variable: – a neodchytí to laděnka (ostatní chyby mi zobrazuje), navíc to ještě pozměnilo konfiguraci php, neboť v php.ini mám, že všechny chyby se logují do souboru a nevypisují se do stránky.
Mám staženou poslední verzi Nette Framework 0.8 (revision 305 released on 2009/05/06 23:15:25) a poslední PHP 5.2.9
- David Grudl
- Nette Core | 8227
Ona totiž Laděnka změní nastavení v php.ini a chyby buď loguje (na produkčním stroji), nebo zobrazuje (na vývojářském).
- Mirek
- Člen | 86
já jsem totiž nějak žil v domění, že se zachytávají i notice,
před časem jsem četl o laděnce na root.cz a utkvěla mě v hlavě věta
o chybách notice „Vnímám je jako upozornění na nejzávažnější
chyby v kódu. Je proto obrovským omylem začátečníků se domnívat, že
tyto chyby mohou zahazovat“, a k pokusům s Nette jsem se dostal až
teď a jaksi jsem předpokládal, že laděnka odchytává i notice.
Článek mě potěšil, neboť k chybám přistupuji obdobně.
Takže, aby mi laděnka odchytávala i notice, tak jsem v debug.php za
řádek 437 připsal další položku pole
E_NOTICE=>1,
Editoval Mirek (11. 6. 2009 11:26)
- jasir
- Člen | 746
Mirek napsal(a):
já jsem totiž nějak žil v domění, že se zachytávají i notice, před časem jsem četl o laděnce na root.cz a utkvěla mě v hlavě věta o chybách notice „Vnímám je jako upozornění na nejzávažnější chyby v kódu. Je proto obrovským omylem začátečníků se domnívat, že tyto chyby mohou zahazovat“, a k pokusům s Nette jsem se dostal až teď a jaksi jsem předpokládal, že laděnka odchytává i notice.
Článek mě potěšil, neboť k chybám přistupuji obdobně.
Takže, aby mi laděnka odchytávala i notice, tak jsem v debug.php za řádek 437 připsal další položku pole
E_NOTICE=>1,
To je dobrý nápad, vyzkouším to. Co takhle pole $fatals přesunout
přímo do debug, aby se dalo napsat:
Debug::$fatals['E_NOTICE'] = 1
; ?
- David Grudl
- Nette Core | 8227
Zkusil jsem to tam dát, zapněte Debug::$strictMode = TRUE
.
Uvidíme, jak se to osvědčí.
- Ondřej Brejla
- Člen | 746
Funguje pěkně, jen se mi to mlátí s csskama webu…nešlo by csska laděnky více specifikovat? Jako, že h1 bude mít takové a takové formátování, ale pouze pokud je v divu s id nette-debug? Nebo jakýpak to element obsahuje laděnku :-) Nebo tak něco…;-)
- Jan Tvrdík
- Nette guru | 2595
David Grudl napsal(a):
Zkusil jsem to tam dát, zapněte
Debug::$strictMode = TRUE
. Uvidíme, jak se to osvědčí.
Pokud je na stránce chyb víc, tak se laděnka nakreslí několikrát přes sebe (vidět je pouze poslední chyba). Zvážil bych, zda při striktním módu nevolat při zachycení první chyby rovnou exit(). Chce ale pořádně zvážil všechny následky, protože mě se nad tím teď přemýšlet nechce :)
- Ondřej Brejla
- Člen | 746
Jan Tvrdík napsal(a):
Pokud je na stránce chyb víc, tak se laděnka nakreslí několikrát přes sebe (vidět je pouze poslední chyba). Zvážil bych, zda při striktním módu nevolat při zachycení první chyby rovnou exit(). Chce ale pořádně zvážil všechny následky, protože mě se nad tím teď přemýšlet nechce :)
Ona ta poslední chyba jde schovat „šipčičkou“ v pravém horním rohu, takže druhou chybu si taky přečtu, ale tu už se mi schovat nepodařilo, protože přes ní byla ta první…;-)
- David Grudl
- Nette Core | 8227
PetrP napsal(a):
je skutečně záhodno aby se v produkčním módu volal exit pro E_NOTICE a podobně? (při strictMode samozřejmě), nestačilo by jen logovat a poslat na mail?
To je určeno čistě pro vývoj, na produkční mašinu se to nehodí.
- LM
- Člen | 206
Co kdyby si Debug
všechny menší chyby ukládal někam bokem a
pokud dojde k nějaké přísnější byly by zobrazeny na bluescreenu taky?
občas se stává že výjimku nebo chybu způsobí nějaká menší ale
laděnka ji zakryje (firebug tohle řeší ale…). Zkusil jsem to implementovat
náhled zde, jde
o blok Previous errors.
- mayo2000
- Člen | 7
Používam NetteFramework-0.9.6-PHP5.2-nonprefix.
Mám zapnutý Debug::$strictMode = TRUE, a v nejakom modeli mám
ociexecute($s, OCI_DEFAULT);
Ktorý generuje warning. V prípade, že som v DEVELOPMENT móde, normálne sa zobrazí ladenka s odchytenou chybou (vlastne ide o warning pretransformovaný na Exception vďaka zapnutému strict módu). Tu problém nie je.
Ale v PRODUCTION móde, by som čakal, že sa chyba dostane až do ErrorPresenteru a zobrazí sa stánka 500 – Internal Error. To sa nedeje. Síce sa pošle Response Header 500, ale stránka je prázdna. Pričom pri umelo vyhodeným výnimkach to funguje OK. Takže tento problém sa týka čisto warningov.
EDIT:
Traceovaním zisťujem, že problém bude, že chyba je vyhadzovaná v modeli a tým pádom sa vynechávajú niektoré fázy v Presenter.php. Ešte ostáva ako to vyriešiť.
Editoval mayo2000 (27. 10. 2010 10:29)
- Aurielle
- Člen | 1281
Nespoléhej na warning, ta funkce musí mít i nějakou návratovou hodnotu… takže otestuj tu a podle toho vyhazuj výjimku. Podle PHP dokumentace by mělo fungovat něco takového:
if(@ociexecute($s, OCI_DEFAULT) === FALSE)
throw new Exception("Something failed...");
Editoval gmvasek (27. 10. 2010 10:17)
- mayo2000
- Člen | 7
Dík gmvasek.
To je celkom dobré riešenie, ktoré kvôli nedostatku času použijem.
Ale myslím, že čistejšie by bolo vylepšiť nette, aby samo vedelo v ktorom modeli nastala výnika a následne vyvolať ErrorPresenter.
Traceovanim som zistil, že je rozdiel medzi prípadom, keď výnimka nastane v Modeli a keď nastane v presenteri.
Ak výnimka nastane v Presenteri tak je flow takýto:
1. Následne v Application.php run() sa v catch bloku sa vytvorí:
$request = new PresenterRequest($this->errorPresenter, PresenterRequest::FORWARD, array('exception' => $e));
2. Debug::processException
3. Výsledkom je že ErrorPresenter vytvorí chybovú stránku
Ak výnimka nastane v modeli:
1. a rovno putuje do Debug::processException, pričom sa nevytvorí PresenterRequest
Editoval mayo2000 (27. 10. 2010 10:58)
- mayo2000
- Člen | 7
No nestačí mi len vlastná výnimka typu „Nastala chyba v spracovaní v databáze“, ale chcel by som minimálne zalogovať reálnu chybu „Invalid parameters into procedure“, ale potlačením @ociexecute sa táto informácia stratí. Myslem som, že riešením je strict mód, ale ten pre zmenu neredirectuje na ErrorPresenter, ak výnimka nastane v modeli.
Editoval mayo2000 (27. 10. 2010 15:17)
- Aurielle
- Člen | 1281
$message = NULL;
Debug::tryError();
ociexecute($s, OCI_DEFAULT);
if(Debug::catchError($message))
{
Debug::log($message, Debug::ERROR);
throw new Exception("Something bad has happened.");
}
Netestováno ale mělo by to fungovat…
edit: tak voda byl zase rychlejší :D
Editoval gmvasek (27. 10. 2010 15:29)
- bene
- Člen | 82
gmvasek napsal(a):
No hlavně v Nette 2.0 se už strictMode nedá použít v produkčním módu (což je dobře), takže bych ti radil spolehnout se na test návratové hodnoty ;)
Je k tomu nějaký důvod?
Mimojiné vzhledem k tomu, že strictMode
automaticky ukončí
vykonávání scriptu (vyjímka je ihned odchycena), což není přesně to
chování, které bych očekával a hlavně chtěl, uvažoval jsem, že za
inicializaci debug si přidám vlastní převádění na vyjímky (viz. níže).
Byla na to již vedená diskuze, aby strictMode
vyjímky vyhazoval
a neodchytával je rovnou, ale David se k tomu tuším nevyjádřil, takže
pokud tohle v Nette 2 nechce zavést, docela by mě zajímal důvod.
něco ve stylu:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
Zkoušel to už někdo nebo má s tím někdo nějaké zkušenosti.
Mé hlavní důvody pro toto chování:
Přístup k neinicializovanému prvku v poli může způsobit v aplikaci
obrovské problémy, zvlášť pokud se ukládá do databáze. Proto je nutné
chyby převádět na vyjímky. Pokud je ale vyjímka ihned odchycena Debugem,
nemohu ji odchytit já a naložit s chybou podle svého.
Dík
- bene
- Člen | 82
S tím se nedá nesouhlasit. Ale ruku na srdce, „bezchybná“ aplikace
„neexistuje“. Zvlášť pokud jde o velkou aplikaci na které se podílí
více lidí.
Osobně si myslím, že strictMode
by měl chyby transformovat na
vyjímky a programátor by se měl rozhodnout, zda ji odchytí nebo nechá
aplikaci padnout do 500 internal server error.
Proč se bráníš přepsání:
} elseif (self::$strictMode && !self::$productionMode) {
self::_exceptionHandler(new \FatalErrorException($message, 0, $severity, $file, $line, $context));
exit;
}
na
} elseif (self::$strictMode) {
throw new \FatalErrorException($message, 0, $severity, $file, $line, $context);
}
?
Mám to odzkoušené a funguje to.
Určitě by nejedno srdce programátora zaplesalo. V PHP by se pracovalo jako v jiných vyspělých jazycích. Dokonce už taková myšlenka padla, aby se chyby převáděly na vyjímky. Takto by se toho docílilo a mohl by to používat jen ten, kdo by chtěl.
To že na serveru by měla být aplikace bez chyb není argument. A krok,
kdy se strictMode
zakáže na produkčním serveru je spíš
házení klacků pod nohy a velké bezpečnostní riziko, že se aplikace
zhroutí, znehodnotí se datbáze, atp. Spíš to beru jako krok zpět než krok
dopředu.
Krok dopředu by byla výše uvedená změna. Kdo nechce, tak si to nezapne.
Kdo si to zapne, nic se pro něj nezmění. A pokud opravdu někdo chce aby
zůstalo stávající chování, PROSÍM, ať je do Debug
přidána
jedna statická proměnná, která mi dovolí zapnout vyhazování vyjímek.
Pokud existuje pádný argument, že výše uvedená změna je špatná, samozřejmě ji akceptuji, ale pokud je to jen názor, že je toto řešení správné bez pádného argumentu, je to pak škoda, že na toto rozhodnutí doplatí ostatní.
Ješte aditační poznámka: Tím že se vypnul strictMode
v produkčním režimu, tím vlastně pozbil smyslu. Protože když aplikaci
ladím ve vývojovém režimu, tak strictMode
nepotřebuji,
protože chyby vidím v debug baru.
Editoval bene (28. 10. 2010 15:45)
- David Grudl
- Nette Core | 8227
StrictMode znamená „náhlá smrt“ a je to alternativní způsob ladění
chyb, kdy se zobrazení v Debug baru nahradí za zobrazení červené
obrazovky. Asi by bylo vhodné $strictMode
přejmenovat na
$immediateDeath
, ale nevím, to druhé se špatně píše :-)
Každopádně tohle nemá s převáděním na výjimky skutečně nic
společného. Ten „převod“ na FatalErrorException je tam čistě
z interních důvodů, protože to zjednodušuje implementaci
Debug::_exceptionHandler
.
Převádění chyb na výjimky v Nette implementováno není a asi nebude, je to moc velký zásah do PHP.