Ankündigung

Einklappen
Keine Ankündigung bisher.

Mit eigenen Errorhandler gezielt Warnungen unterdrücken

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Mit eigenen Errorhandler gezielt Warnungen unterdrücken

    Hi,
    unterdrückte Warnungen können die Fehlersuche erheblich erschweren.
    Aus Bequemlichkeit werden nicht selten einige PHP Funktionen für Zwecke benutzt, bei denen ein Erfolg nicht immer gegeben ist.
    Ein typischer Fall ist ein file_get_contents auf die URL eines nicht immer verfügbaren Servers.
    Im Falle des Misserfolges werden werden Warnungen geworfen, die für diesen Fall unterdrückt werden sollen.
    Nun gibt es ja den bei Anfängern beliebten Fehler-Kontroll-Operator @, doch dieser ist nicht umsonst verpönt,
    denn er unterdrückt alle Fehler. Beispiel mit falsch geschriebenen Funktionsnamen:
    PHP-Code:
    //so nicht!
    $r = @file_get_content('testdatei.txt');  //Keine Fehlermeldung 
    Spannend wird die Problematik für ein include.
    Hier sollen gezielt nur Warnungen vom include der obersten Ebene unterdrückt werden.
    Angeregt durch nikoschs Ausführungen hier im Forum entstand folgende Lösung:

    PHP-Code:
    <?php
      error_reporting
    (-1);

      
    $errHandler = function ($errcode$errmsg$fileName$line) {
        return 
    $errcode == E_WARNING 
          
    && strpos($errmsg,'include(') !== false
          
    && $fileName == __FILE__ ;
      };

      
    set_error_handler($errHandler);
     
      
    //include, das eine Warnung erzeugen würde
      
    $include_ok = include 'noexist.php';
      
    //Nutzung einer undefinierten Konstante  
      
    $include2_ok = include myincludeName;
      
    //Funktionsaufruf der Warnung erzeugt
      
    $include3_ok = include file_get_contents('dateiname.txt');
      
      
    restore_error_handler();
      
      
    var_dump('include results:',$include_ok,$include2_ok,$include3_ok);
    Fehler, Notizen und Warnungen, die nicht vom include kommen, werden alle ausgegeben.
    So auch alle Warnungen, die im Falle eines Erfolges aus dem include-File kommen.


    Code:
    Notice: Use of undefined constant myincludeName ... on line 15
    
    Warning: file_get_contents(dateiname.txt) ...failed to open stream ... on line 17
    string(20) "
    include results:" bool(false) bool(false) bool(false)
    Um die Wirkung des eigenen Error-Handlers sichtbar zu machen, muß nur die Zeile mit 'set_error_handler...' mal auskommentiert werden.
    Dann sehen wir alle include-Warnungen wie gewohnt.

    Wofür nun dieser 'Aufwand' ?
    Ich habe bisher nur einen Fall wo ich es brauche.
    Es ist ein Autoloader, in dem mit include verschiedene Muster von Dateinamen/Pfaden bis zum Erfolg probiert werden müssen.
    Gegenüber der Variante per is_readable alle Kombinationen von include-Pfaden und Dateinamesmuster zu prüfen,
    ist der Aufwand dieser Lösung hier noch klein und mit nur sehr geringen Einbußen in Bezug auf die Scriptlaufzeit.

    Probleme bisher keine, alle Tests liefen zufriedenstellend.
    Eine Kleinigkeit wird sich noch in der Praxis zeigen, ob die Bedingung
    PHP-Code:
    strpos($errmsg,'include(') !== false 
    eventuell noch zu weich ist und durch ein regEx ersetzt werden muss.

    Kommentare sind jedoch immer willkommen.

    LG jspit
    PHP-Klassen auf github

  • #2
    PHP-Code:
    $fileName == __FILE__ 
    Ähm ja... das ist schon ein wenig grenzwertig. Dann kannst du auch einfach @include() schreiben.

    Wenn dann würde ich das so umsetzen: (auch wenn damit nicht unterscheidbar ist welches include)

    PHP-Code:
    class IncludeException extends ErrorException {
    }


    function(
    $errno$errstr$errfile$errline, array $errcontext) {
        if(
    $errcode == E_WARNING && strpos($errmsg,'include(') !== false) {
            throw new 
    IncludeException($errstr0$errno$errfile$errline);
        }
        
        throw new 
    ErrorException($errstr0$errno$errfile$errline);

    Und dann mit:

    PHP-Code:
    try {
       include(
    'gibt.net');
    } catch (
    IncludeException $e) {} 

    Kommentar


    • #3
      Zitat von erc Beitrag anzeigen
      PHP-Code:
      $fileName == __FILE__ 
      Ähm ja... das ist schon ein wenig grenzwertig. Dann kannst du auch einfach @include() schreiben.
      Die Bedingung sorgt dafür, daß include-Warnungen die aus dem Includefile selbst oder tiefer verschachtelten kommen auch gezeigt werden. Ich sehe nicht, was daran 'grenzwertig' sein soll.
      Edit: Mit __FILE__ ist jedoch die Bedingung verbunden, den errHandler in der gleichen Datei zu definieren in der auch die include-Anweisung steht. Ist aber für mein Fall kein Problem.

      @include() macht ja alles an Fehlern und Warnungen platt was im include-file auftreten kann und darunter.

      Die Idee eine Exception für den Fall der Unterdrückung zu werfen ist aber nicht schlecht, wer es mag. Ich selbst arbeite kaum mit Exceptions.
      PHP-Klassen auf github

      Kommentar


      • #4
        Zitat von jspit Beitrag anzeigen
        Ich sehe nicht, was daran 'grenzwertig' sein soll.
        Edit: Mit __FILE__ ist jedoch die Bedingung verbunden, den errHandler in der gleichen Datei zu definieren in der auch die include-Anweisung steht. Ist aber für mein Fall kein Problem.
        Das find ich ebend sehr unschön. Die "Fehlerbehandlung" sollte einmal festgelegt werden und sich nicht ändern.

        Zitat von jspit Beitrag anzeigen
        @include() macht ja alles an Fehlern und Warnungen platt was im include-file auftreten kann und darunter.
        Ach, alles klar. Ich habe seit Jahren kein @ mehr benutzt, ganz schlechte Erfahrungen damit gemacht. Ein Projekt in dem vor jedem mysql_query und mysql_fetch... ein @ stand, schön.

        Zitat von jspit Beitrag anzeigen
        Die Idee eine Exception für den Fall der Unterdrückung zu werfen ist aber nicht schlecht, wer es mag. Ich selbst arbeite kaum mit Exceptions.
        Ich finde Exceptions bei weitem angenehmer als das false zurückgebe und irgendwelchen error flags und co.

        Kommentar


        • #5
          Zitat von erc Beitrag anzeigen
          Die "Fehlerbehandlung" sollte einmal festgelegt werden und sich nicht ändern.
          Vom Grundsatz her schon. Doch es wäre nicht schön und das ist nicht mein Ziel, für alle includes im Script die Warnungen abzuschalten. Denn diese kommen im Normalfall nicht ohne Grund . Die Warnung möchte ich temporär nur für die Fälle abschalten, wo ich include gewissermaßen mißbrauche. Der restore_error_handler(); steht da deshalb auch nicht ohne Grund.

          LG jspit
          PHP-Klassen auf github

          Kommentar


          • #6
            Zitat von jspit Beitrag anzeigen
            Vom Grundsatz her schon. Doch es wäre nicht schön und das ist nicht mein Ziel, für alle includes im Script die Warnungen abzuschalten.
            Kostet ein file_exists oder is_readable wirklich soviel mehr Leistung das sich das lohnt?

            Kommentar


            • #7
              Siehe Paralleldiskussion: http://www.php.de/php-fortgeschritte...te-klasse.html

              [edit] die andere
              --

              „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
              Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


              --

              Kommentar

              Lädt...
              X