Zobrazení chyby ve stránce

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

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

_Martin_
Generous Backer | 679
+
0
-

Laděnka standardně noticky neodchytává – pouze pokud používáš FireBug s FirePHP, odchytí je a zobrazí v něm. Pokud jde o logování do souboru, tipuji, že Laděnka detekovala vývojový režim a proto chyby neloguje, ale vypisuje.

David Grudl
Nette Core | 8227
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

Zkusil jsem to tam dát, zapněte Debug::$strictMode = TRUE. Uvidíme, jak se to osvědčí.

Ondřej Brejla
Člen | 746
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

nojo, ten exit jsem tam zapomněl…

PetrP
Člen | 587
+
0
-

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?

jasir
Člen | 746
+
0
-

David Grudl napsal(a):

Zkusil jsem to tam dát, zapněte Debug::$strictMode = TRUE. Uvidíme, jak se to osvědčí.

Tak můžu říct, že mě se s tímhle nastavení pracuje skvěle. Přeci jen textík „Undefined variable…“ někde v layoutu se dá snadno přehlédnout. Takhle je to fakt paráda…

David Grudl
Nette Core | 8227
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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
+
0
-

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)

Aurielle
Člen | 1281
+
0
-

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 ;)

mayo2000
Člen | 7
+
0
-

Dobré vedieť.

V tomto prípade, by to chcelo metódu Debug::getLastException().

Aby sa dalo napísať:

if(@ociexecute($s, OCI_DEFAULT) === FALSE) {
    throw new Exception(Debug::getLastException());
}
Aurielle
Člen | 1281
+
0
-

K čemu chceš poslední výjimku? Nějak nechápu… vždyť tam akorát stačí vyhodit vlastní výjimku kterou si zpracuješ ErrorPresenterem… nic víc nepotřebuješ ;)

mayo2000
Člen | 7
+
0
-

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)

voda
Člen | 561
+
0
-

Na to by mohlo pomoct tryError a catchError.

Aurielle
Člen | 1281
+
0
-
$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
+
0
-

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

Aurielle
Člen | 1281
+
0
-

Chyby v aplikaci nemají na produkčním serveru co dělat. Nemělo by se tam vyskytnout žádné neinicializované pole nebo něco podobného, pro toto slouží development mód na localhostu (+ strict).

bene
Člen | 82
+
0
-

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)

pekelnik
Člen | 462
+
0
-

Immediate Death vs. Convert To Exception se tu už několikrát řešilo…

AFAIK jsme se nikdy nedobrali řešení ANO/NE.

mě by se to samozřejmě líbilo…

David Grudl
Nette Core | 8227
+
0
-

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.