Errorhandling
Bobby
- php
Moin
ich habe es nun mal geschaft mich nach ewigen Zeiten mal mit ordentlichem Errorhandling zu beschäftigen.
ich habe in meiner config-Datei, die ich überall einbinde folgende Zeilen zur Exception-Behandlung eingefügt:
error_reporting(0);
include("func.class.php");
$func = new \inc\Func();
function shutdown()
{
global $func;
$a=error_get_last();
if($a!==null)
$func->savePHPException($a['message'],1,$a['file']." : ".$a['line'],WEBDIR.'error.html');
}
function exception_error_handler($errno, $errstr, $errfile, $errline) {
global $func;
if ($errno!=8)
$func->savePHPException($errstr,$errno,$errfile." : ".$errline);
}
register_shutdown_function('shutdown');
set_error_handler("exception_error_handler");
Die Func hat dann folgende Zeilen:
function savePHPException($message,$code,$aktion,$ziel=false)
{
foreach($GLOBALS as $key=>$value)
if ($key!='GLOBALS')
$errarr[$key]=$value;
$file=LOCALDIR."phperror.txt";
$fp=fopen($file,"a");
if ($fp!==FALSE)
fwrite($fp,$message.'|'.$code.'|'.$aktion.'|'.json_encode($errarr).'|'.date(time())."\n");
if (PRODUCTION===TRUE):
echo $message.'<br/>'.CHR(10).$code.'<br/>'.CHR(10).$aktion.'<br/>';
else:
if (!empty($ziel)):
header('Location:'.$ziel);
exit();
endif;
endif;
}
Ist das Vorgehen Korrekt?
Ein ähnliches Vorgehen habe ich bei PDO-Fehlern gewählt.
Was könnte verbessert werden?
Gruß Bobby
hi,
Ist das Vorgehen Korrekt?
Dein Gesamtkonzept ist mir nicht klar. Hier ist meins:
Ich setze alles, was schiefgehen kann, in deinen try-Block, die geamte Ausgabe wird dazu gepuffert.
error_get_last() wirft bei mir eine Exception, nützlich vor allem während der Entwicklung.
Mit error_get_last() kriegst du den letzten, dann den vorletzten usw. und schließlich kriegst Du die alle ;)
Ein ähnliches Vorgehen habe ich bei PDO-Fehlern gewählt.
Stichwort: Exception chaining. PDO-Ex. werden bei mir durchgereicht.
Fehlerhafte Benutzereingaben werfen bei mir auch Ex. aber die fange ich weiter oben ab, wo ich noch HTML ausgeben und der Benutzer seine Eingabe korrigieren kann.
Was könnte verbessert werden?
Machs nicht so kompliziert ;)
Horst
Moin
Dein Gesamtkonzept ist mir nicht klar. Hier ist meins:
Ich dachte mir ich zeige dem Nutzer nicht was schief gegangen ist. Dies logge ich ja mit.
Ich setze alles, was schiefgehen kann, in deinen try-Block, die geamte Ausgabe wird dazu gepuffert.
Ok, Ausgabepuffer wollte ich umgehen, da mein View bereits einen Puffer erzeugt. Die beschriebene Function fängt alles was PHP-Fehler sind ab und speichert diese.
error_get_last() wirft bei mir eine Exception, nützlich vor allem während der Entwicklung.
Mit error_get_last() kriegst du den letzten, dann den vorletzten usw. und schließlich kriegst Du die alle ;)
Das verwende ich nur bei Fatal-Errors.
Ein ähnliches Vorgehen habe ich bei PDO-Fehlern gewählt.
Stichwort: Exception chaining. PDO-Ex. werden bei mir durchgereicht.
Fehlerhafte Benutzereingaben werfen bei mir auch Ex. aber die fange ich weiter oben ab, wo ich noch HTML ausgeben und der Benutzer seine Eingabe korrigieren kann.
Hm... das ist eine Überlegung wert.
Danke für deine Hinweise. Werd mal sehn was sich draus machen lässt.
Gruß Bobby
hi,
Dein Gesamtkonzept ist mir nicht klar. Hier ist meins:
Ich dachte mir ich zeige dem Nutzer nicht was schief gegangen ist. Dies logge ich ja mit.
Wäre auch ok, solange sich jemand ums Log bemüht. Es wäre aber auch ok, dem Benutzer zu zeigen, dass was schiefgegangen ist, z.B. keine DB-Verbindung, in den meisten Fällen macht da eh nur ein Abbruch Sinn.
Also: der Benutzer sollte nicht zuviel sehen, aber wenigstens soviel, dass er das auch buchstabieren und in dringenden Fällen damit den Support anrufen kann.
Ok, Ausgabepuffer wollte ich umgehen, da mein View bereits einen Puffer erzeugt. Die beschriebene Function fängt alles was PHP-Fehler sind ab und speichert diese.
Auch ok, es wäre die Frage, wie weit Du die Pufferung spannst und vor Allem das Sammeln von Fehlermeldungen betreiben willst (für eine dem Benutzer verständliche FM mit der Möglichkeit zur Korrektur).
Mit error_get_last() kriegst du den letzten, dann den vorletzten usw. und schließlich kriegst Du die alle ;)
Das verwende ich nur bei Fatal-Errors.
if error_get_last() throw Exception ;)
Viel Spaß noch,
Horst
PS: "Entwicklergetrieben Loggen" tu ich nur, wenn es keine andere Möglichkeit gibt, einem vertrackten Fehler auf die Schliche zu kommen. D.h., ich würde das machen, wenn...
Moin
Wäre auch ok, solange sich jemand ums Log bemüht. Es wäre aber auch ok, dem Benutzer zu zeigen, dass was schiefgegangen ist, z.B. keine DB-Verbindung, in den meisten Fällen macht da eh nur ein Abbruch Sinn.
Deshalb ja die individuellen Weiterleitunsgziele. Für DB-Fehler kann ich vorher ein Weiterleitungsziel im Fehlerfall setzen (z.B. DB-Error, oder nur eine Einblendung einer mit Javascript erzeugten Fehlerbox mit Rückleitung zurück) Da ist alles denkbar, und entsprechend vorbereitet.
Also: der Benutzer sollte nicht zuviel sehen, aber wenigstens soviel, dass er das auch buchstabieren und in dringenden Fällen damit den Support anrufen kann.
Ja, das passiert. Die Ausnahmeseite wird nur im FATAL-Fehlerfall aufgerufen (PHP Fatal Fehler, Keine Verbidnung zur DB, da diese Elementar ist)
Für andere Fehler, wie gesagt individuelle Fehlerseiten. Aber eben soweit heruntergebrochen, dass ich nicht für jeden Fehlerfalle ine einzelne Exception habe, sondern eine gesamte.
Auch ok, es wäre die Frage, wie weit Du die Pufferung spannst und vor Allem das Sammeln von Fehlermeldungen betreiben willst (für eine dem Benutzer verständliche FM mit der Möglichkeit zur Korrektur).
Benutzereingaben prüfe ich noch klassisch ohne Exception. Dein Tipp ist aber bei mir angekommen, dies ebenfalls über Exceptions zui lösen. DAs halte ich für überaus sinnvoll.
PS: "Entwicklergetrieben Loggen" tu ich nur, wenn es keine andere Möglichkeit gibt, einem vertrackten Fehler auf die Schliche zu kommen. D.h., ich würde das machen, wenn...
Naja, ich möchte für jede Eventualität gerüstet sein. Zum Beispiel hatte ich letztens das Phänomen, dass ein Server in seinem Memory-Limit beschränkt war (nicht von PHP sondern von der tatsächlich verfügbaren Speichergröße). Da konnte in der PHP.Ini drinstehn was wollte. Dort erschien nun immer der "out of memory"-Fehler. Der Kunde hielt mich nun zu blöd das ordentlich zu programmieren, da es ja auf dem Entwicklungsrechner ging. Und die Meldung hat er natürlich nicht aufgeschrieben. :)
Ich hoffe du verstehst mein Ansinnen. ;)
Ich werde jedoch über die Ansätze nachdenken... Dank für die konstruktiven Hinweise...
Gruß Bobby
Meine Herren!
Dein Gesamtkonzept ist mir nicht klar. Hier ist meins:
Ich dachte mir ich zeige dem Nutzer nicht was schief gegangen ist. Dies logge ich ja mit.
In einer Produktiv-Umgebung sollte man das auch nicht machen. In einer Enwticklungs-Umgebung ist es m.M.n. angenehmer, Fehler direkt zu sehen und nicht erst im Error-Log nachzusehen.
Fehlerhafte Benutzereingaben werfen bei mir auch Ex. aber die fange ich weiter oben ab, wo ich noch HTML ausgeben und der Benutzer seine Eingabe korrigieren kann.
Hm... das ist eine Überlegung wert.
Die Herangehensweise wird kontrovers diskutiert. Die Debatte wurde erst neulich auf net-tuts geführt. Es gilt, wie so oft, abzuwägen.
Moin
In einer Produktiv-Umgebung sollte man das auch nicht machen. In einer Enwticklungs-Umgebung ist es m.M.n. angenehmer, Fehler direkt zu sehen und nicht erst im Error-Log nachzusehen.
Deswegen habe ich ja eine Konstante "PRODUCTION" etabliert. Auf true gesetzt zeigt es mir die Fehler direkt an (und loggt mit). Auf false wird nur mittgeloggt und auf Fehlerseite weitergeleitet.
Das habe ich also bereits bedacht. ;)
Die Herangehensweise wird kontrovers diskutiert. Die Debatte wurde erst neulich auf net-tuts geführt. Es gilt, wie so oft, abzuwägen.
Danke für den Link. Werd ich dann mal durcharbeiten.
Gruß Bobby
In einer Produktiv-Umgebung sollte man das auch nicht machen. In einer Enwticklungs-Umgebung ist es m.M.n. angenehmer, Fehler direkt zu sehen und nicht erst im Error-Log nachzusehen.
Deswegen habe ich ja eine Konstante "PRODUCTION" etabliert. Auf true gesetzt zeigt es mir die Fehler direkt an (und loggt mit). Auf false wird nur mittgeloggt und auf Fehlerseite weitergeleitet.
Sollte die dann nicht eher DEBUG oder so heißen?
MfG
bubble
Moin
Sollte die dann nicht eher DEBUG oder so heißen?
Bisschen haarspalterisch... aber recht hast du.... ;)
Gruß Bobby
Mahlzeit,
Bisschen haarspalterisch... aber recht hast du.... ;)
Naja, wenn mir ein Entwickler was bringt, was mit der Einstellung "PRODUCTION" Fehler im Browser ausgibt, würde ich den auch spalten ;)
Moin
Naja, wenn mir ein Entwickler was bringt, was mit der Einstellung "PRODUCTION" Fehler im Browser ausgibt, würde ich den auch spalten ;)
Ich habs ja verstanden und auf DEBUG geändert...
Gruß Bobby
Moin,
Fehlerhafte Benutzereingaben werfen bei mir auch Ex. aber die fange ich weiter oben ab, wo ich noch HTML ausgeben und der Benutzer seine Eingabe korrigieren kann.
Hm... das ist eine Überlegung wert.
Exceptions vereinfachen die Kontrolle; wenn alles, was die Response erzeugt, gepuffert ist, kann ich mit
die("Falsches Datum\n"); # perl
eine Ex werfen, wobei mit dem \n der Backtrace unterdrückt wird. Im Zuge der Entwicklung kann ich mit
$self->dd($var); # perl dump & die; Ausgabe text/plain
einen Dump im Browser ausgeben, um nur mal eben zu schauen, wie trefflich $var aussieht. Ich kann aber auch in einer Parameter-Kontrollstruktur mit
tie my $date, 'TieDate', date => $self->param('date') or
return $self->errorP(title => 'Eingebafehler', descr => 'Falsches Datum');
einen FehlerParagraphen oben einblenden, das Eingabeformular ist unter der Fehlermeldung weiterhin sichtbar, der Benutzer kann seine Eingabe korrigieren (Affenformular).
Horst
Mahlzeit,
evtl. hilft dir auch noch xDebug weiter, da der Backtrace ausführlicher ist.
Moin
evtl. hilft dir auch noch xDebug weiter, da der Backtrace ausführlicher ist.
Klingt auch sehr spannend. Danke.
Ich merk schon, dass ich auch um Unit-Test nicht drumherum kommen werde.
Gruß Bobby
Mahlzeit,
Ich merk schon, dass ich auch um Unit-Test nicht drumherum kommen werde.
Ein "Viel Spass damit" wäre jetzt sehr ironisch :D
Auch wenns manchmal nötig ist, Unit-Tests find ich pfui ;)
Aber alleine schon die Profiler-Funktion hilft, um Bottlenecks zu finden. Unter Linux gibts da geile Tools um sowas grafisch darzustellen, unter Windows vermutlich auch.
Moin
Ein "Viel Spass damit" wäre jetzt sehr ironisch :D
Auch wenns manchmal nötig ist, Unit-Tests find ich pfui ;)
Ich weiß, deshalb habe ich mich bisher gescheut...
Aber alleine schon die Profiler-Funktion hilft, um Bottlenecks zu finden. Unter Linux gibts da geile Tools um sowas grafisch darzustellen, unter Windows vermutlich auch.
Wie gesagt... muss ich mich mal näher damit beschäftigen...
Gruß Bobby