602 Stimmen

Wie fange ich einen fatalen PHP-Fehler (`E_ERROR`) ab?

Ich kann set_error_handler() um die meisten PHP-Fehler abzufangen, aber es funktioniert nicht bei fatalen ( E_ERROR ) Fehler, wie z.B. der Aufruf einer Funktion, die nicht existiert. Gibt es eine andere Möglichkeit, diese Fehler abzufangen?

Ich versuche zu telefonieren mail() für alle Fehler und ich verwende PHP 5.2.3.

673voto

user259973 Punkte 6567

Protokollieren Sie schwerwiegende Fehler mit der Funktion register_shutdown_function , die PHP 5.2+ erfordert:

register_shutdown_function( "fatal_handler" );

function fatal_handler() {
    $errfile = "unknown file";
    $errstr  = "shutdown";
    $errno   = E_CORE_ERROR;
    $errline = 0;

    $error = error_get_last();

    if($error !== NULL) {
        $errno   = $error["type"];
        $errfile = $error["file"];
        $errline = $error["line"];
        $errstr  = $error["message"];

        error_mail(format_error( $errno, $errstr, $errfile, $errline));
    }
}

Sie müssen die error_mail y format_error Funktionen. Zum Beispiel:

function format_error( $errno, $errstr, $errfile, $errline ) {
    $trace = print_r( debug_backtrace( false ), true );

    $content = "
    <table>
        <thead><th>Item</th><th>Description</th></thead>
        <tbody>
            <tr>
                <th>Error</th>
                <td><pre>$errstr</pre></td>
            </tr>
            <tr>
                <th>Errno</th>
                <td><pre>$errno</pre></td>
            </tr>
            <tr>
                <th>File</th>
                <td>$errfile</td>
            </tr>
            <tr>
                <th>Line</th>
                <td>$errline</td>
            </tr>
            <tr>
                <th>Trace</th>
                <td><pre>$trace</pre></td>
            </tr>
        </tbody>
    </table>";
    return $content;
}

Verwenden Sie Schneller Versand zum Schreiben der error_mail Funktion.

Siehe auch:

172voto

periklis Punkte 9872

Ich habe gerade diese Lösung gefunden (PHP 5.2.0+):

function shutDownFunction() {
    $error = error_get_last();
     // Fatal error, E_ERROR === 1
    if ($error['type'] === E_ERROR) {
         // Do your stuff
    }
}
register_shutdown_function('shutDownFunction');

Verschiedene Fehlertypen sind definiert unter Vordefinierte Konstanten .

122voto

keparo Punkte 32084

PHP bietet keine konventionellen Mittel zum Abfangen und Wiederherstellen von fatalen Fehlern. Das liegt daran, dass die Verarbeitung nach einem schwerwiegenden Fehler normalerweise nicht wiederhergestellt werden sollte. Ein String-Matching eines Ausgabepuffers (wie im Originalbeitrag vorgeschlagen, ist die auf PHP.net beschriebene Technik definitiv nicht ratsam. Es ist einfach unzuverlässig.

Auch der Aufruf der Funktion mail() aus einer Error-Handler-Methode heraus erweist sich als problematisch. Bei vielen Fehlern wäre Ihr Mailserver überlastet, und Sie könnten einen unübersichtlichen Posteingang vorfinden. Um dies zu vermeiden, könnten Sie einen Cron laufen lassen, der die Fehlerprotokolle regelmäßig überprüft und entsprechende Benachrichtigungen sendet. Sie könnten sich auch mit Systemüberwachungssoftware befassen, z. B. mit Nagios .


Um auf den Teil über die Registrierung einer Abschaltfunktion einzugehen:

Es stimmt, dass man eine Abschaltfunktion registrieren kann, und das ist eine gute Antwort.

Der Punkt hier ist, dass wir normalerweise nicht versuchen sollten, uns von fatalen Fehlern zu erholen, vor allem nicht, indem wir einen regulären Ausdruck gegen Ihren Ausgabepuffer verwenden. Ich reagierte auf die akzeptierte Antwort , die auf einen Vorschlag auf php.net verweist, der inzwischen geändert oder entfernt wurde.

Der Vorschlag lautete, während der Ausnahmebehandlung einen Regex gegen den Ausgabepuffer zu verwenden und im Falle eines schwerwiegenden Fehlers (der durch den Abgleich mit dem von Ihnen erwarteten konfigurierten Fehlertext erkannt wird) zu versuchen, eine Art Wiederherstellung oder Weiterverarbeitung durchzuführen. Das wäre keine empfohlene Vorgehensweise (ich glaube, das ist auch der Grund, warum ich den ursprünglichen Vorschlag nicht finden kann. Entweder habe ich ihn übersehen, oder die php-Community hat ihn abgeschossen).

Es ist vielleicht erwähnenswert, dass die neueren PHP-Versionen (etwa 5.1) die shutdown-Funktion früher aufrufen, bevor der Ausgabepufferungs-Callback aufgerufen wird. In Version 5 und früher war die Reihenfolge umgekehrt (auf den Aufruf der Ausgabepufferung folgte die Shutdown-Funktion). Außerdem werden seit etwa 5.0.5 (das ist viel früher als die Version 5.2.3 des Fragestellers) Objekte entladen, bevor eine registrierte Shutdown-Funktion aufgerufen wird, so dass Sie sich nicht darauf verlassen können, dass Ihre In-Memory-Objekte irgendetwas tun.

Die Registrierung einer Shutdown-Funktion ist also in Ordnung, aber die Art der Aufgaben, die von einer Shutdown-Funktion ausgeführt werden sollten, sind wahrscheinlich auf eine Handvoll sanfter Shutdown-Prozeduren beschränkt.

Das Wichtigste, was man hier mitnehmen kann, sind ein paar weise Worte für jeden, der über diese Frage stolpert und den Ratschlag in der ursprünglich akzeptierten Antwort sieht. Regexen Sie Ihren Ausgabepuffer nicht.

68voto

LugiHaue Punkte 2516

Fatale Fehler oder wiederherstellbare fatale Fehler werfen nun Instanzen von Error en PHP 7 oder höhere Versionen . Wie alle anderen Ausnahmen, Error Objekte können mit einer try/catch Block.

Beispiel:

<?php
$variable = 'not an object';

try {
    $variable->method(); // Throws an Error object in PHP 7 or higger.
} catch (Error $e) {
    // Handle error
    echo $e->getMessage(); // Call to a member function method() on string
}

https://3v4l.org/67vbk

Oder Sie können verwenden Throwable Schnittstelle, um alle Ausnahmen abzufangen.

Beispiel:

<?php
    try {
        undefinedFunctionCall();
    } catch (Throwable $e) {
        // Handle error
        echo $e->getMessage(); // Call to undefined function undefinedFunctionCall()
    }

https://3v4l.org/Br0MG

Für weitere Informationen: http://php.net/manual/en/language.errors.php7.php

37voto

sakhunzai Punkte 12935

Nun, es scheint möglich zu sein, fatale Fehler auf andere Weise abzufangen :)

ob_start('fatal_error_handler');

function fatal_error_handler($buffer){
    $error = error_get_last();
    if($error['type'] == 1){
        // Type, message, file, line
        $newBuffer='<html><header><title>Fatal Error </title></header>
                      <style>
                    .error_content{
                        background: ghostwhite;
                        vertical-align: middle;
                        margin:0 auto;
                        padding: 10px;
                        width: 50%;
                     }
                     .error_content label{color: red;font-family: Georgia;font-size: 16pt;font-style: italic;}
                     .error_content ul li{ background: none repeat scroll 0 0 FloralWhite;
                                border: 1px solid AliceBlue;
                                display: block;
                                font-family: monospace;
                                padding: 2%;
                                text-align: left;
                      }
                      </style>
                      <body style="text-align: center;">
                        <div class="error_content">
                             <label >Fatal Error </label>
                             <ul>
                               <li><b>Line</b> ' . $error['line'] . '</li>
                               <li><b>Message</b> ' . $error['message'] . '</li>
                               <li><b>File</b> ' . $error['file'] . '</li>
                             </ul>

                             <a href="javascript:history.back()"> Back </a>
                        </div>
                      </body></html>';

        return $newBuffer;
    }
    return $buffer;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X