try, catch, exception, error klasse
Davinchi
- php
Liebe SelfHTMLer,
ich bin auf der Suche nach einem Konzept.
Bisher und ich weiß - das ist sehr sehr unüberlegt, dumm, ungeplant gewesen, werden bei mir alle Fehler direkt ausgegeben, mit der Bitte, dem Admin(mir) eine E-Mail zu schreiben.
Ich habe also intuitiv programmiert was ich brauchte (immerhin OOP) aber Fehlerbehandlung? Nix da.
Nun sind das ganz schön viele Klassen geworden und Wenn ein Fehler stattfindet, heißt es suchen.
Ich möchte folgendes haben:
Fehler werden nicht mehr angezeigt sondern in einem Error-Log gespeichert.
Also heißt das ja zum Beispiel erst einmal, das ich jeden Funktionsaufruf bzw Query mit einem @ davor aufrufe, danach weiß ich halt noch nicht wie ich vorgehe.
Entweder ich setze um jeden "schei**", ein try/catch block und üübergebe die exceptions an die Fehler-Behandlungsklasse, oder ich frage den Erfolg per IF ab.
Wie geht ihr da vor, macht mal Vorstellungen, gebt man Ideen und Lösungsansätze. Sehr sehr gerne auch Code. Swohl richtigen als auch "Pseudo".
Gruß,
der davinchi
Hi,
Ich möchte folgendes haben:
Fehler werden nicht mehr angezeigt sondern in einem Error-Log gespeichert.Also heißt das ja zum Beispiel erst einmal, das ich jeden Funktionsaufruf bzw Query mit einem @ davor aufrufe, danach weiß ich halt noch nicht wie ich vorgehe.
Nein.
Den @-Operator sollte man vermeiden, weil er langsam ist - er bewirkt bei jeder einzelnen Verwendung ein "Stummschalten" des error reportings, und direkt danach wird es wieder auf den vorher eingestellten Wert gesetzt.
Wenn du Meldungen von PHP nicht in der Ausgabe sehen, sondern geloggt haben willst, dann konfiguriere es entsprechend - siehe http://www.php.net/manual/en/errorfunc.configuration.php
MfG ChrisB
Wenn du Meldungen von PHP nicht in der Ausgabe sehen, sondern geloggt haben willst, dann konfiguriere es entsprechend - siehe http://www.php.net/manual/en/errorfunc.configuration.php
Okay du hast Recht.
Danke dafür!
echo $begrüßung;
Fehler werden nicht mehr angezeigt sondern in einem Error-Log gespeichert.
Also heißt das ja zum Beispiel erst einmal, das ich jeden Funktionsaufruf bzw Query mit einem @ davor aufrufe, danach weiß ich halt noch nicht wie ich vorgehe.
Entweder ich setze um jeden "schei**", ein try/catch block und üübergebe die exceptions an die Fehler-Behandlungsklasse, oder ich frage den Erfolg per IF ab.
Das allein reicht nicht. Auftretende Fehler versauen einem den schönsten Programmablauf. Man muss die potentiellen Fehler gleich von vorn herein in seine Programmplanung aufnehmen, denn wenn erstmal einer aufgetreten ist, heißt es zu entscheiden, was am besten zu tun ist. Wie schwerwiegend ist der Fehler? Kann man korrigierenden Code verfassen und im Programm weitermachen? Muss man einen alternativen Weg gehen, um trotz Fehler die Verarbeitung doch noch zu einem geordneten Abschluss zu bringen? Vor allem sollte man beim Überlegen den Anwender nicht vergessen. Der sitzt vor einen System, das auf einmal nicht weitermachen will. Wie ist dem Anwender in dem Fall so geholfen, dass er trotzdem da bleibt und nicht beispielsweise sein Geld zur Konkurrenz trägt?
Wie geht ihr da vor, macht mal Vorstellungen, gebt man Ideen und Lösungsansätze. Sehr sehr gerne auch Code. Swohl richtigen als auch "Pseudo".
Die Anforderungen einerseits und Fehlermöglichkeiten andererseits sind so vielfältig, dass es schwer ist, das in generell gültigen Code zu bringen.
Ein bei jedem Fehler anspringender Log-Mechanismus ist auch nicht in jedem Fall angebracht. Oft lässt man es absichtlich auf Fehler ankommen, statt vorher alles abzuprüfen. Denn zwischen Prüfung und Ausführung der eigentlich gewollten Handlung können in Mehrbenutzersystemen Änderungen auftreten, die den gezogenen Schluss aus der Prüfung hinfällig machen, weil das Prüfungsergebnis durch die geänderten Voraussetzungen nicht mehr stimmt. Also führt man einfach die gewünschte Handlung aus und hofft dass alles gut geht. Wenn nicht, informiert man den Anwender, dass ihm irgendwer zuvorgekommen ist. Der Administrator muss von dem ganzen Vorgang nichts mitbekommen, denn in der Situation kann er auch nicht weiterhelfen.
Der Code zur Fehlererkennung und der daraufhin auszuführende Code können mitunter größer werden als der Code der eigentlichen Aufgabe. Das Loggen für den Administrator fällt dabei kaum ins Gewicht, dafür kann man sich eine Funktion schreiben, dir nur noch mit den aktuelle Daten (Wo ist es passiert? Was ist passiert? Welche Umstände (Variableninhalte) führten dazu?) aufgerufen werden muss. Wichtig ist, sich in jedem konkreten Einzelfall Gedanken zu machen, denn ein Rundumsorglospaket bestehend lediglich aus
include 'fehlerbehandlung.php';
gibt es nicht.
echo "$verabschiedung $name";
Hello,
[...] Oft lässt man es absichtlich auf Fehler ankommen, statt vorher alles abzuprüfen.
Man sollte die Rückmeldungen von Programmteilen auch nicht als Fehler bezeichnen, sondern eben als "Rückmeldung". Dass PHP daraus "Fehler" gemacht hat, ist ein Fehler ;-)
Und viel schlimmer ist es, dass man die Rückmeldungen, speziell der mit Systemaufrufen beauftragten Funktionen, nicht sauber abfangen kann.
Ein
if (file_exists('filename'))
{
$fh = fopen('filename', 'r');
}
sieht zwar nett aus, ist aber nur gewollt und nicht gekonnt.
Hier wäre es besser, gleich ausschließlich mit einem fopen() arbeiten zu dürfen, und den "Fehler" abfangen zu können, und zwar mit so genauer Klassifizierung, wie möglich, natürlich nicht als dubiosen Klartext, sondern als numerischen Wert.
Aber vielleicht bauen die PHP-Entwickler das ja bis zur Version 10 noch ein :-(
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Ja ich kann dir nur zustimmen.
Aber mir reicht es zu wissen wie kompetente User wie du, Sven rautenberg, Felix Risterer, Ingo und andere beschreiben wie sie es handhaben.
Klar, das ich auf Fehler reagieren muss, das der Anwender nicht vor einem großen ERROR hockt - ist klar.
Aber wie sag ich der "logging"-Funktion
DU BEFINDEST DICH: Datei, Klasse, Funktion, Zeile und der Fehler ist ein PHP oder MySQL Fehler UND den Fehler lautet: XXX
Ich denke mal die ersten Sachen bekomme ich durch __FILE__, __CLASS__, __FUNCTION__ aber den Rest?
Ich arbeite btw mit MySQLi, OOP genutzt.
Liebe Grüße,
Davinchi
Hello,
das Wesentliche dabei ist wohl die Unterscheidung zwischen unerwarteten Fehlern, für die es dann vermutlich auch keine Behandlung gibt und erwarteten "Fehlern" - also Statusmeldungen, die man behandeln muss.
Wenn sich eine datei nicht öffnen lässt, war dieser vorhersehbar.
$fh = fopen('filename','r');
if (!$fh)
{
## Fehlerbehandlung
}
PHP macht einem aber eine qualifizierte Fehlerbehandlung sehr schwer, da es keine Fehlernummern zur Verfügung stellt, sondern nur Fehlertexte. Um an diese heranzukommen, muss man Aufwand treiben:
z.B.:
ini_set('track_errors', 1);
$php_errormsg = false;
$fh = fopen('filename','r');
if (!$fh)
{
##Fehlerbehandlung
if (!empty($php_errormsg) and get_errno($php_errormsg)) ## selber schreiben!
{
# ...
}
}
Erst dann kannst Du entscheiden, was geschehen soll.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
ich weiß leider nicht, seit welcher PHP-Version das funktioniert, aber in derjenigen, die ich hier auf dem XAMPP habe (PHP 5.2.5) kann man die Informationen abfragen, auch ohne einen eigenen Error-Handler zu definieren. Im Handbuch steht für die Funktion error_get_last() die Ver 5.2.0:
<?php ### error.php ###
#error_reporting(~E_WARNING); ## [1]
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
echo "<br />\r\n";
echo "Error-Nr: " . $errno . "<br />\r\n";
echo "Error-String: " . $errstr . "<br />\r\n";
echo "Error-String: " . $errfile . "<br />\r\n";
echo "Error-String: " . $errline . "<br />\r\n";
return false;
}
#$old_error_handler = set_error_handler("myErrorHandler"); ## [2]
$fh = fopen('unbekannt.txt','rb+');
echo "<pre>\r\n";
echo htmlspecialchars(print_r(error_get_last(),1));
echo "</pre>\r\n";
#clearstatcache(); ## [3]
$fh = fopen('unbekannt.txt','rb'); ## [4a]
#$fh = fopen('unbekannt.txt','rb+'); ## [4b]
?>
Zum Spielen einfach mal die gekennzeichneten Zeilen auskommentieren, die mit a/b gekennzeichneten sinnvollerweise wechselseitig.
Daran sieht man, dass die Fehlerbehandlung in PHP noch sehr fehlerhaft ist.
Mich stört daran insbesondere, dass Fehlermeldungen, die die darunterliegende Plattform erzeugt, einfach verschluckt werden. Die sind nämlich meistens so aussagekräftig, dass man mit ihrer Kenntnis viel besser reagieren könnte.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
echo $begrüßung;
Aber wie sag ich der "logging"-Funktion
DU BEFINDEST DICH: Datei, Klasse, Funktion, Zeile und der Fehler ist ein PHP oder MySQL Fehler UND den Fehler lautet: XXX
Im Kapitel Error Handling and Logging gibt es unter anderem eine Funktion debug_backtrace(). Die zeigt dir die gesamte Aufrufreihenfolge bis zum aktuellen Zeitpunkt inklusive der Parameterwerte von Funktionen. Den aktuellen Inhalt der Variablen im derzeitigen Kontext bekommt man mit einem get_defined_vars(). Und wenn track_errors eingeschaltet ist, findet man den Text des Fehlers in der Variable $php_errormsg. get_defined_vars() und $php_errormsg muss man nur dann selbst angeben, wenn der Fehler händisch geloggt wird. Wenn du einen Error-Handler schreibst, bekommt der bis auf den Debug-Trace automatisch alles übergeben. Allerdings springt dieser auch bei mit @ unterdrückten Fehlern an. Diesen Zustand kann man durch Abfragen des Rückgabewertes von error_reporting() ermitteln, denn der ist dan 0.
Auf den @ kann man nicht generell verzichten. Gerade wenn man in einigen Fällen so arbeitet, dass man Fehler erwartet und dafür die Meldung nicht braucht muss man sie mit @ ausschalten. Das error_reporting generell auf 0 zu setzen bringt nichts, weil man dann im Error-Handler nicht mehr gewollte und ungewollte Fehler voneinander unterscheiden kann. Wann so ein @-Fall eintritt merkt mann beim Entwickeln und Testen, denn man testet ja auch ausgiebig die Fehlerfälle (wenn man eine robuste Anwendung schreiben will).
Ein Beispiel dazu ist getimagesize(). Wenn mich der Unterschied zwischen "ist zwar vorhanden aber keine Bilddatei" und "Datei existiert nicht oder ist nicht lesbar" nicht interessiert, dann muss ich auch nicht aufwendig vorher mit file_exists() oder is_readable() darauf testen. Es reicht dann, einfach getimagesize() aufzurufen und false als Rückgabewert zu erwarten. Dummerweise (in meinem Fall) gibt es dabei eine Warnung, die man weder sehen noch loggen will, also: @. Generell sollte man den @ nicht überstrapazieren sondern nur nach ausgiebigen Tests und wohl überlegt einsetzen.
Die Konfiguration von error_reporting sollte man im Labor und in der Produktivumgebung auf E_ALL stehen haben. Für die Produktivumgebung ist ein Logging erforderlich, sonst ist das E_ALL sinnlos. display_errors sollte man nur im Labor eingeschaltet haben oder aber seinen Error-Handler so programmiert haben, dass er die Fehler anzeigt, damit man sofort eine Rückmeldung bekommt, dass da noch eine Baustelle offen ist.
Und zu guter Letzt sei noch die Funktion trigger_error() erwähnt, mit der man gezielt Fehlermeldungen erzeugen kann, die man dann im eigenen Error-Handler loggen kann. Der Vorteil dabei ist, dass man wie bei "richtigen" Fehlern den aktuellen Kontext mit übergeben bekommt.
echo "$verabschiedung $name";