Bobby: Errorhandling

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

--
-> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
### Henry L. Mencken ###
-> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
## Viktor Frankl ###
ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
  1. 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

    1. 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

      --
      -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
      ### Henry L. Mencken ###
      -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
      ## Viktor Frankl ###
      ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
      1. 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...

        1. 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

          --
          -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
          ### Henry L. Mencken ###
          -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
          ## Viktor Frankl ###
          ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
      2. 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.

        --
        “All right, then, I'll go to hell.”
        1. 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

          --
          -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
          ### Henry L. Mencken ###
          -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
          ## Viktor Frankl ###
          ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
          1. 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

            --
            If "god" had intended us to drink beer, he would have given us stomachs. - David Daye
            1. Moin

              Sollte die dann nicht eher DEBUG oder so heißen?

              Bisschen haarspalterisch... aber recht hast du.... ;)

              Gruß Bobby

              --
              -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
              ### Henry L. Mencken ###
              -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
              ## Viktor Frankl ###
              ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
              1. 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 ;)

                --
                42
                1. 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

                  --
                  -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
                  ### Henry L. Mencken ###
                  -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
                  ## Viktor Frankl ###
                  ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
      3. 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

  2. Mahlzeit,

    evtl. hilft dir auch noch xDebug weiter, da der Backtrace ausführlicher ist.

    --
    42
    1. 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

      --
      -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
      ### Henry L. Mencken ###
      -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
      ## Viktor Frankl ###
      ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
      1. 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.

        --
        42
        1. 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

          --
          -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
          ### Henry L. Mencken ###
          -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
          ## Viktor Frankl ###
          ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)