Heiko: Fehler Warnings etc abfangen und am ENDE des Script anzeigen

Hallöchen,

Ich habe eine Fehlerroutine gefunden, die mir eigentlich so ganz gut gefällt. Das Problem ist nur, das eventuelle Fehler zwischen den Script angezeigt werden.

Mein Wunsch jedoch wäre es, diese formatiert am Ende als Liste anzuzeigen.
Kann mir jemand erklären, wie ich diese Variablen in ein Array speichern kann und bei Bedarf das Array abzufragen?

  
function customError($errno, $errstr, $errfile, $errline) {  
    echo "<b>Error:</b> [$errno] $errstr<br>";  
    echo "Line: ".$errline."<br>";  
    echo "File: ".$errfile."<br><br>";  
    die();  
}  
set_error_handler("customError");  

Vielen Dank.

Heiko

  1. Tach!

    Ich habe eine Fehlerroutine gefunden, die mir eigentlich so ganz gut gefällt.

    Warum gefällt dir diese? Bringt sie dir einen Nutzen, den dir die originale PHP-Fehlermeldung nicht liefert?

    Das Problem ist nur, das eventuelle Fehler zwischen den Script angezeigt werden. Mein Wunsch jedoch wäre es, diese formatiert am Ende als Liste anzuzeigen.

    Ja und? Fehler, die man nicht erwartet und vom Script sowieso behandeln lässt, sind doch dazu da, dass man ihre Ursache beseitigt oder die Abfangroutinen erweitert. Fehlermeldungen werden nicht nützlicher, wenn man sie an eine andere Stelle verbannt. Eine kaputte Ausgabe wird wieder heile, wenn man sich des Fehlers und seiner Ursache angenommen hat.

    Ich sähe ja einen Sinn in einem eigenen Errorhandler, wenn der im produktiven Betrieb bei Fehlern eine Meldung an den Administrator absetzt. Selbst im Entwicklungsstadium kann er nützlich sein, wenn er gleich von sich aus zusätzliche Informationen ermittelt, die man in der Regel sowieso wissen möchte. Beispielsweise den Aufrufstack oder alle Variablen im aktuellen Kontext.

    Kann mir jemand erklären, wie ich diese Variablen in ein Array speichern kann und bei Bedarf das Array abzufragen?

    Was genau soll man dir daran erklären? Wie man ein Array anlegt? Wie man ein Array außerhalb einer Funktion anlegt, also global? Wie man auf Variablen, insbesondere Arrays zugreift?

    dedlfix.

    1. Hi,

      sag mal, wie behandelst du (der Profi) denn Fehler* in einem Skript? Gibt es dazu eine best practice?

      * Eigentlich meine ich  gar nicht zwingend PHP-Fehler, sondern eher Debug-Ausgaben oder eigene Fehler (zum Beispiel Unplausibilitäten oder fehlerhafte Validierung von Werten).

      Viele grüße
      solstheimer

      1. Tach!

        sag mal, wie behandelst du (der Profi) denn Fehler* in einem Skript? Gibt es dazu eine best practice?

        Am besten scheint mir, dass man sich zunächst mal bewusst ist, welche Fehler auftreten können. Da man das kaum bis zur Vollständigkeit vorausschauen kann, sollte man vor allem herausfinden, wie Fehler signalisiert werden. Dies steht im PHP-Handbuch beschrieben. In der Regel gibt eine Funktion im Fehlerfall etwas anderes zurück als im Gut-Fall. Wenn man diese Information im Code auswertet, dann ist das schon mal der erste wichtige Schritt. Und ja, mit Fehlerauswertungscode wird das Script unter Umständen um ein Vielfaches größer als wenn man nur die Sonnenscheinvariante programmiert.

        Was macht man nun mit dem gefangenen Fehler? Kann man den Fehler voraussehen und kennt eine Alternative, wie der Besucher dennoch zu seinem Ziel kommen kann, dann sollte man diese implementieren. Wenn nicht, wäre eine Tröstmeldung in Richtung Anwender und eine Benachrichtigung in Richtung Administrator sinnvoll. Keinesfalls sollte man den genauen Fehlermeldungstext mit irgendwelchen Systeminterna drin ausgeben, und auch nicht einfach so das Script sterben lasen. Normalerweise kann der Anwender nichts für den auftretenden Fehler und er sollte auch nicht dafür mit einer Meldung bestraft werden, mit der er nichts anfangen kann.

        * Eigentlich meine ich  gar nicht zwingend PHP-Fehler, sondern eher Debug-Ausgaben oder eigene Fehler (zum Beispiel Unplausibilitäten oder fehlerhafte Validierung von Werten).

        Debug-Ausgaben gebe ich unter PHP üblicherweise schlicht und einfach mit einem var_dump() aus. Ein <pre> davor spart bei komplexen Strukturen den Blick in die Quelltextansicht des Browsers. Debug-Ausgaben kommen nach dem Debugvorgang wieder raus, also gebe ich mir auch keine gesteigerte Mühe, sie schön aussehen zu lassen oder sie schön in die Ausgabe einzufügen. In dem Augenblick geht es darum, den Fehler im PHP-Code zu finden und dabei ist das Ergebnis im Browser nicht weiter relevant. Es muss deshalb auch kein valider Code entstehen, also ist ein schließendes </pre> unnötig.

        Selbst erzeugte Fehlermeldungen, also beispielsweise wenn beim Validieren der Eingabewerte unerlaubte Werte festgestellt werden, sind nochmal eine andere Kategorie für sich. Die gehören ja zur Geschäftslogik und werden je nach deren Anforderung behandelt. Solche gehen auf die Kappe des Anwenders und müssen in Zusammenarbeit mit ihm geklärt werden.

        Das waren die Varianten für überschaubare Projekte. Nun gibt es zum Beispiel auch noch Bibliotheken und andere wiederverwendbare Codestücke, bei denen man nicht weiß, in welcher Umgebung sie letztlich laufen werden. Da kann man gleich gar nicht einfach so Fehler ausgeben. Wenn man nicht selbst darauf reagieren kann, bleibt nur das ordentliche Melden an den Aufrufer, über eine Exception oder einen speziellen Rückgabewert.

        Außerdem gibt es da noch die schwierigen Fälle, wenn sich der Fehler im Labor partout nicht nachstellen lässt. Dann bleibt nicht viel anderes übrig als den Code mit Log-Ausgaben zu spicken. Dafür gibt es fertig verwendbare Bibliotheken. Man muss dann "nur" noch seinen Code mit Log-Aufrufen spicken und einmal zentral definieren, wohin die Meldung gehen soll.

        dedlfix.

  2. Mein Wunsch jedoch wäre es, diese formatiert am Ende als Liste anzuzeigen.
    Kann mir jemand erklären, wie ich diese Variablen in ein Array speichern kann und bei Bedarf das Array abzufragen?

    1.)
    Warum ein Array? Ein String genügt.

    2.,)
    Im Übrigen macht es nur Sinn den ersten Fehler anzusehen. Grund: Viele Fehler ziehen eine ganze Wulst _vermeintlicher_ weiterer Fehler nach sich.

      
    // Das hier gehört in eine Konfigurationsdatei. Damit wird festgelegt, ob die Fehlerausgabe überhaupt stattfindet.  
    // Auf arbeitenden Servern sollte das vermieden werden.  
    define('DEBUG_On_Screen',TRUE);  
      
      function customError($errno, $errstr, $errfile, $errline, $fatal=FALSE) {  
         // Ob der Parameter fatal auf TRUE gesetzt wird musst Du beim Aufruf entscheiden.  
         // Dann wird das Programm "abgebrochen" und der Fehler ausgegeben.  
      
         // Globaler Speicher:  
         if (! isset($GLOBALS['Custom Errortext'])) {  
              $GLOBALS['Custom Errortext']='';  
         }  
         // Anhängen:  
         $GLOBALS['Custom Errortext'].= "  
    ######################################################################  
    Error:</b> [$errno] $errstr  
    Line: $errline  
    File: $errfile  
    ######################################################################  
    ";  
         // Prüfen auf Ausgabe:  
         if ($fatal && DEBUG_On_Screen) {  
              PrintCustomError();  
         }  
     }
    

    Diese Funktion nochmals ganz am Ende(!) aufrufen:

     function PrintCustomError() {  
         // Prüfen ob $GLOBALS['Custom Errortext'] existiert und einen Inhalt hat:  
         if (DEBUG_On_Screen && isset($GLOBALS['Custom Errortext']) && $GLOBALS['Custom Errortext'] != '') {  
             // Ausgabe und exit  
             print '<pre style="display:block;visibility:visible;position:absolute;z-index:99">  
    '.$GLOBALS['Custom Errortext'].</pre>';  
             exit;  
         }  
     }
    

    Dieser Code ist in "Phantastoskript" geschrieben und eine Handlungsanleitung welche die prinzipielle Vorgehensweise zeigt und soll nur eine umständliche oder unverständliche Beschreibung in menschlicher Sprache vermeiden. Er kann also fehlerhaft sein. Ähnlichkeiten zu PHP, Perl, Java, Javascript, Basic,  VBA, VBS, C, C++ oder jeder anderen Programmiersprache sind rein zufällig.

    In der Realität wird übrigens nicht mit einem einfachen DEBUG_On_Screen=true|false gearbeitet, sondern mit einem DEBUG_LEVEL um eine abgestufte Fehlerreaktion zu ermöglichen.

    1. Tach!

      Warum ein Array? Ein String genügt.

      Im Prinzip ja. Aber warum gleich die Ausgabeformatierung an der datenerzeugenden Stelle vornehmen, noch dazu ohne jegliche Kontextbeachtung? Sowas ist bei den produktiven Teilen eines Script schon sehr nachteilig, weil man sich damit die weiteren Verwendungsmöglichkeiten auf "Ausgeben" einschränkt. Man kann das EVA-Prinzip auch bei solchen nur für den Programmierer nützlichen Funktionen einhalten, wenn es um mehr als einen zu Debug-Zwecken temporär eingefügten Code-Schnipsel geht. Die Sinnhaftigkeit des Vorgehens habe ich ja auch angezweifelt, aber wenigstens ordentlich kann man es ja machen. Das übt dann wenigstens für die wichtigen Sachen.

      function customError($errno, $errstr, $errfile, $errline, $fatal=FALSE) {
           // Ob der Parameter fatal auf TRUE gesetzt wird musst Du beim Aufruf entscheiden.

      Diese Funktion ist eine Callback-Funktion, die von PHP aufgerufen wird. Der Programmierer hat keine Chance, im Fehlerfall den $fatal-Parameter zu setzen. Da diese Funktion also nicht für einen manuellen Aufruf vorgesehen ist, ist ein Erweitern ihrer Signatur nicht sinnvoll, zumal der fünfte Parameter bereits eine Bedeutung hat. Siehe set_error_handler(). Der Teil mit dem $fatal ist also fatal falsch.

      Dieser Code ist in "Phantastoskript" geschrieben

      Warum zeichnest du dann den Code als PHP aus? PHP steht nicht für PHantastoskriPt.

      und eine Handlungsanleitung welche die prinzipielle Vorgehensweise zeigt und soll nur eine umständliche oder unverständliche Beschreibung in menschlicher Sprache vermeiden. Er kann also fehlerhaft sein. Ähnlichkeiten zu PHP, Perl, Java, Javascript, Basic,  VBA, VBS, C, C++ oder jeder anderen Programmiersprache sind rein zufällig.

      Mit anderen Worten: "Ich hab meine Lösung nicht mit der Realität verglichen. Der Disclaimer soll eigentlich nur vorbeugen, dass mir niemand wegen Fehlern ans Bein pinkeln kann." Ach, Fredstix, Du solltest doch wissen, dass solche Disclaimer nichts bringen.

      dedlfix.

      1. Der Disclaimer soll eigentlich nur vorbeugen, dass mir niemand wegen Fehlern ans Bein pinkeln kann.

        Nun, dieses "ans Bein pinkeln" ist leider eine Unart in diesem Forum und hat meiner Auffassung nach mit dem Niedergang des selben zu tun. Statt zu helfen wird hier zu viel "angepisst" - und Deine Äußerung zeigt deutlich, dass GENAU das der Zweck Deiner "Hilfe" ist.

        Fred

        1. Tach!

          Nun, dieses "ans Bein pinkeln" ist leider eine Unart in diesem Forum und hat meiner Auffassung nach mit dem Niedergang des selben zu tun. Statt zu helfen wird hier zu viel "angepisst" - und Deine Äußerung zeigt deutlich, dass GENAU das der Zweck Deiner "Hilfe" ist.

          Eigentlich versuche ich dir zu helfen, deine Fehler zu erkennen. Ich denke nicht, dass man mit falschen Lösungen dem Ruf des Forum oder den Fragenden dient. Anscheinend ist dir mehr daran gelegen, das gleich als Angriff denn als Chance für eine technische Diskussion zu sehen.

          dedlfix.

        2. Hallo,

          Nun, dieses "ans Bein pinkeln" ist leider eine Unart in diesem Forum und hat meiner Auffassung nach mit dem Niedergang des selben zu tun. Statt zu helfen wird hier zu viel "angepisst"

          das sehe ich völlig anders: Viele Hinweise und Anregungen, die man hier bekommt, zielen eigentlich darauf ab, dass andere dem Fragesteller eben _nicht mehr_ so leicht ans Bein pinkeln können.

          Ciao,
           Martin

          --
          Dem Philosoph ist nichts zu doof.
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(