it-swarm.com.de

Stoppen Sie die Skriptausführung nach Benachrichtigung/Warnung

Ist es möglich, PHP die Ausführung nach einer Benachrichtigung/Warnung global zu stoppen?

Wir betreiben einen Entwicklungsserver mit vielen Websites, möchten aber unsere Entwickler zwingen, diese Warnungen/Hinweise zu korrigieren (oder zumindest um Hilfe bitten), anstatt sie zu ignorieren und weiterzugehen.

35
Michael

Ja, es ist möglich. Diese Frage bezieht sich auf die allgemeinere Frage, wie Fehler in PHP behandelt werden sollen. Sie sollten einen benutzerdefinierten Fehlerbehandler definieren und registrieren, indem Sie set_error_handler verwenden.docs um die Handhabung für PHP -Fehler anzupassen.

IMHO ist es am besten, eine Ausnahme bei jedem PHP - Fehler auszulösen und Try/Catch-Blöcke zu verwenden, um den Programmfluss zu steuern, aber die Meinungen unterscheiden sich in diesem Punkt.

Um das erklärte Ziel des OP zu erreichen, können Sie Folgendes tun:

function errHandle($errNo, $errStr, $errFile, $errLine) {
    $msg = "$errStr in $errFile on line $errLine";
    if ($errNo == E_NOTICE || $errNo == E_WARNING) {
        throw new ErrorException($msg, $errNo);
    } else {
        echo $msg;
    }
}

set_error_handler('errHandle');

Der obige Code wirft eine ErrorException jedes Mal, wenn ein E_NOTICE oder E_WARNING ausgelöst wird, wodurch die Skriptausgabe effektiv beendet wird (wenn die Ausnahme nicht abgefangen wird). Das Auslösen von Ausnahmen bei PHP -Fehlern wird am besten mit einer parallelen Ausnahmebehandlungsstrategie ( set_exception_handler ) kombiniert, um in Produktionsumgebungen ordnungsgemäß zu beenden.

Beachten Sie, dass das obige Beispiel den @-Fehlerunterdrückungsoperator nicht berücksichtigt. Wenn dies für Sie wichtig ist, fügen Sie einfach einen Check mit der Funktion error_reporting() hinzu, wie hier gezeigt:

function errHandle($errNo, $errStr, $errFile, $errLine) {
    if (error_reporting() == 0) {
        // @ suppression used, don't worry about it
        return;
    }
    // handle error here
}
48
rdlowrey

Ab PHP 5.3.0:

set_error_handler(
    function(int $nSeverity, string $strMessage, string $strFilePath, int $nLineNumber){
        if(error_reporting()!==0) // Not error suppression operator @
            throw new \ErrorException($strMessage, /*nExceptionCode*/ 0, $nSeverity, $strFilePath, $nLineNumber);
    },
    /*E_ALL*/ -1
);
6

Sie können dies global in Ihrer Datei php.ini konfigurierenDocs .

Dazu geben Sie eine Datei an, die von allen PHP - Prozessen mit der Direktive auto_prepend_file eingeschlossen wirdDocs :

auto_prepend_file "/full/path/to/a/prepend-file.php"

Wenn Sie dies in Ihrer globalen php.ini-Datei tun, wird sichergestellt, dass der Code in der vorangegangenen Datei immer ausgeführt wird. Sie können es dann verwenden, um einen globalen Fehlerbehandler zu registrieren, der alle Fehler in Ausnahmen umwandeltDocs :

<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

Dieses kleine Skript verwandelt alle Fehler/Warnungen/Hinweise usw. in eine ErrorException .

Kombinieren Sie es mit der Ini-Direktive error_reportingDocs , die Werte sind in Ihrer php.ini-Datei beschrieben.

Eine Ausnahme zu werfen ist eine sehr strikte Sache. Ihre Programmierer werden gezwungen sein, mit Warnungen und Fehlern umzugehen, sonst funktioniert der Code nicht.

Wahrscheinlich ist dies für Ihre Programmierer zu viel und in Ihrem Unternehmen nicht sozial akzeptabel. Stattdessen können Sie auch alle Fehler protokollieren und am Ende der Ausgabe hinzufügen (oder oben, damit sie besser sichtbar ist), indem Sie die Ausgabepufferung verwenden.

Eine andere Alternative besteht darin, Fehler und Warnungen in der Protokolldatei zu protokollieren und diese Datei anschließend mit einem anderen Prozess zu überwachen und die Informationen zusammenzufassen. Sie können eine Anzeigetafel erstellen, die die Anzahl der Warnungen pro Anwendung anzeigt und diese im Büro sichtbar macht, sodass jeder sieht, wie gut ein Team funktioniert oder so etwas Spaß macht.

Was ich zu sagen versuche: Neben dem technischen Problem ist es ein soziales Problem, mit dem Sie kreativ sein und das Problem Ihren Entwicklern tatsächlich ausreden müssen. Sie müssen klarstellen, warum es wichtig ist, Warnungen und Fehler zu beheben, und wie deren Kodierung und Fähigkeiten davon profitieren.

6
hakre

Wenn Sie sich in einer Entwicklungsumgebung befinden, können Sie das Modul Xdebug installieren und xdebug.halt_level=E_WARNING|E_NOTICE|E_USER_WARNING|E_USER_NOTICE irgendwo in Ihren PHP - INI-Dateien angeben. Der Entwickler kann xdebug.halt_level zurücksetzen, wir haben jedoch dasselbe Problem mit der Antwort, die auf set_error_handler basiert, da der ursprüngliche Wert des Handlers wiederhergestellt werden kann. 

3
user2066805

Die anderen Lösungen implementieren eine benutzerdefinierte Fehlerbehandlungsroutine, die den Standardmechanismus für die Fehlerprotokollierung überschreibt. Das heißt, wenn wir einen benutzerdefinierten Fehlerhandler festlegen, wird der Hinweis/die Warnung nicht mehr in der Standardeinstellung gedruckt, sodass wir mehr als nur "Skriptausführung bei Hinweis/Warnung stoppen" ändern.

Ich brauchte jedoch eine Möglichkeit, die Nachricht trotzdem auszudrucken - in meinem Fall in PHP CLI -, da die Ausgabe dann von einem anderen Programm analysiert wird. Deshalb wollte ich die Nachricht nicht in - ausdrucken. irgendwie aber genau so wie PHP normalerweise. Ich nur wollte aufhören das = PHP CLI-Prozess mit einem Exit-Code von != 0 unmittelbar nachdem ein Hinweis/eine Warnung gedruckt wurde, und tun nichts anderes ändern.

Leider scheint es keine Standardmethode zum Beenden des Skripts zu geben, ohne die gesamte Fehlerbehandlung zu ändern. Also musste ich den Standard-Fehlerbehandler (der in C implementiert ist) in PHP neu implementieren.

Dazu habe ich mich mit dem Standard-Fehlerdruckmechanismus im PHP-Quellcode befasst und die relevanten Teile von C nach PHP) portiert, um den folgenden Fehlerhandler zu erhalten, den ich für Sie freigeben möchte brauche etwas ähnliches:

set_error_handler(
    function($errNo, $errStr, $errFile, $errLine) {
        $error_type_str = 'Error';
        // Source of the switch logic: default error handler in PHP's main.c
        switch ($errNo) {
            case E_ERROR:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
                $error_type_str = "Fatal error";
                break;
            case E_RECOVERABLE_ERROR:
                $error_type_str = "Recoverable fatal error";
                break;
            case E_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
            case E_USER_WARNING:
                $error_type_str = "Warning";
                break;
            case E_PARSE:
                $error_type_str = "Parse error";
                break;
            case E_NOTICE:
            case E_USER_NOTICE:
                $error_type_str = "Notice";
                break;
            case E_STRICT:
                $error_type_str = "Strict Standards";
                break;
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                $error_type_str = "Deprecated";
                break;
            default:
                $error_type_str = "Unknown error";
                break;
        }
        fwrite(STDERR, "PHP $error_type_str:  $errStr in $errFile on line $errLine\n");
        exit(1);
    },
    E_ALL
);
1
leemes