PHP Errors verarbeiten

MsWord

Mitglied
Hallo zusammen,

ich schreibe mir ein kleines System.
Nun möchte ich verhindern das die PHP Fehler ausgegeben werden (ini_set('display_errors', 0)), aber ich möchte das ich diese in einer eigenen LogDatei geschrieben werden, zudem noch eine E-Mail an den Admin mit den Fehlern senden und eine Offlineseite ausgeben lassen ("Zur Zeit ist unsere Webseite nicht erreichbar... blablabla").

Ich habe mal ein wenig gesucht und bin auf die "set_error_handler()" Funktion gestoßen.
Nur leider Funktionieren die Beispiele dazu nur teilweise. Denn wenn ich versuche eine nicht existierende Funktion aufzurufen, bricht er einfach dort ab und führt nicht die Funktion aus.

Hat jemand dazu eine Lösung parat? Oder einen besseren Lösungsweg?

PHP:
<?php
function myErrorHandler($fehlercode, $fehlertext, $fehlerdatei, $fehlerzeile)
{
    if (!(error_reporting() & $fehlercode)) {
        // Dieser Fehlercode ist nicht in error_reporting enthalten
        return;
    }

    switch ($fehlercode) {
    case E_USER_ERROR:
        echo "<b>Mein FEHLER</b> [$fehlercode] $fehlertext<br />\n";
        echo "  Fataler Fehler in Zeile $fehlerzeile in der Datei $fehlerdatei";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
        echo "Abbruch...<br />\n";
        exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>Meine WARNUNG</b> [$fehlercode] $fehlertext<br />\n";
        break;

    case E_USER_NOTICE:
        echo "<b>Mein HINWEIS</b> [$fehlercode] $fehlertext<br />\n";
        break;

    default:
        echo "Unbekannter Fehlertyp: [$fehlercode] $fehlertext<br />\n";
        break;
    }

    /* Damit die PHP-interne Fehlerbehandlung nicht ausgeführt wird */
    return true;
}

// Error Reporting off
ini_set( "display_errors", 0 );

error_reporting(E_ALL);
#ini_set('display_errors', 1);

$alter_error_handler = set_error_handler("myErrorHandler");

// Funktion zum Test der Fehlerbehandlung
function logarithmisch_skalieren($vektor, $skalierung)
{
    if (!is_numeric($skalierung) || $skalierung <= 0) {
        trigger_error("log(x) ist für x <= 0 nicht definiert, Sie verwendeten: skalierung = $skalierung", E_USER_ERROR);
    }

    if (!is_array($vektor)) {
        trigger_error("Fehlerhafter Eingabevektor, es wird ein Wertearray erwartet", E_USER_WARNING);
        return null;
    }

    $temp = array();
    foreach($vektor as $pos => $wert) {
        if (!is_numeric($wert)) {
            trigger_error("Der Wert an Position $pos ist keine Zahl, verwende 0 (Null)", E_USER_NOTICE);
            $wert = 0;
        }
        $temp[$pos] = log($skalierung) * $wert;
    }

    return $temp;
}

// ein paar Fehler auslösen, zuerst wird ein gemischtes Array mit einem
// nichtnumerischen Eintrag definiert
echo "Vektor a\n";
$a = array(2, 3, "foo", 5.5, 43.3, 21.11);
print_r($a);

// ein zweites Array erzeugen
echo "----\nVektor b - ein Hinweis (b = log(PI) * a)\n";
/* Der Wert an Position $pos ist keine Zahl, verwende 0 (Null) */
$b = logarithmisch_skalieren($a, M_PI);
print_r($b);

// das gibt Ärger: statt eines Arrays wird eine Zeichenkette übergeben
echo "----\nVektor c - eine Warnung\n";
/* Fehlerhafter Eingabevektor, es wird ein Wertearray erwartet */
$c = logarithmisch_skalieren("kein Array", 2.3);
var_dump($c); // NULL

// dies ist ein kritischer Fehler: log ist für Null oder negative Werte
// nicht definiert
echo "----\nVektor d - fataler Fehler\n";
/* log(x) ist für x <= 0 nicht definiert, Sie verwendeten: skalierung = $skalierung */
$d = logarithmisch_skalieren($a, -2.5);
var_dump($d); // wird nie erreicht

// Diese Funktion existiert nicht
example_xyz();
 

sheel

I love Asm
Anderer Ansatz: Kannst du mir ein Beispiel sagen,
wo sich PHP-Fehler nicht durch besseren Code verhindern lassen?
 

saftmeister

Nutze den Saft!
Aufrufen einer nichtvorhandenen Funktion sollte nicht abgefangen, statt dessen, wie schon von sheel geschrieben, im Code korrigiert werden. Ansonsten kann man mit set_error_handler() keine fatalen Fehler abfangen. Steht aber auch schon im Manual zu dieser Funktion:

http://php.net/manual/de/function.set-error-handler.php hat gesagt.:
Die folgenden Fehlertypen können nicht von einer benutzerdefinierten Funktion behandelt werden: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING und die meisten E_STRICT, die in der Datei ausgelöst werden, in der set_error_handler() aufgerufen wird.

Es gibt einen Workarround für das Abfangen fataler Fehler: register_shutdown_function(). Problematisch an der Sache ist, dass, sollte im Handler für die registrierte Funktion ebenfalls ein Fehler gefunden werden, der fatal ist, dreht sich die Sache im Kreis und man hat recht schnell eine Rekursion, die nicht aufgelöst werden kann, was im schlimmsten Fall weitere Probleme verursacht (Logfile wird zu groß, Emails, die den Vorfall melden bringen das Postfach zum überquellen, etc.). Falls du dennoch den Weg gehen willst, benötigst du noch die Funktion error_get_last().