Fehlermeldungen in PHP sind in den Standardstellungen schon relativ ergiebig, allerdings zeigen sie noch lange nicht alles an, was möglich ist. Aus diesem Grund habe ich die unten angehängten Funktionen erstellt, welche eine ausführliche Ausgabe erzeugen.

Zunächst empfehle ich jedem das Fehlerlevel auf die höchste Empfindlichkeit zu stellen. Das geschieht mittels der Funktion “error_reporting()“.  Die Einstellungen sollten jedoch nur im Entwicklungssystem gelten. Für das Produktsystem ist ein schwächeres Level empfehlenswert.

error_reporting( E_ALL | E_STRICT );

Des weiteren sollte man das Loggen in eine Datei mittels “ini_set()” aktivieren.

ini_set( 'error_log', 'path_to_the_log_file/errors.log' );

Die beiden Funktionen für das Error- und Exceptionhandling werden mittels “set_exception_handler()” und “set_error_handler()” aktiviert. Der Errorhandler führt dabei lediglich eine Weiterleitung auf den Exceptionhandler durch. Das hat den Vorteil, dass beide Fehlerarten auf die gleiche Weise behandelt werden. Eine Typangabe zeigt aber trotzdem die ursprüngliche Quelle. Wie bereits beim Logfile sollte man das  Fehlerlevel im Produktsystem abschwächen.

require_once ( 'path_to_the_include_file/errorHandler.php' );
set_exception_handler( 'exceptionHandler' );
set_error_handler( 'errorHandler', E_ALL | E_STRICT );

Um das Verhalten der Handler zu steuern, gibt es zwei Konstanten. Mittels “EXCEPTION_HANDLER_OUTPUT” kann man über die Werte “live” und “mail” angeben, ob die Ausgabe im Browser erfolgen oder eine Mail versendet werden soll. Die notwendige Mailadresse wird mittels “EXCEPTION_HANDLER_MAIL_RECEIVER” definiert. Standard ist eine Ausgabe im Browser also der Wert “live”. Beispiel für eine Ausgabe als Mail:

define( 'EXCEPTION_HANDLER_OUTPUT', 'mail' );
define( 'EXCEPTION_HANDLER_MAIL_RECEIVER', 'mail@example.com' );

Die Ausgabe enthält folgende Daten:

  • Datei, in welcher der Fehler aufgetreten ist.
  •  Zeile, in welcher der Fehler aufgetreten ist.
  • Fehlerart (Exception oder Error).
  • Fehlerbeschreibung.
  • URL, unter welcher der Fehler aufgetreten ist.
  • Inhalt von $_GET, $_POST und $_COOKIE.
  • Ein kurzer Stacktrace.
  • Ein ausführlicher Stacktrace mit der kompletten Laufzeitumgebung.

Im Folgenden der Quellcode für die Handler-Funktionen. Er kann auch von mediafire.com heruntergeladen werden.

/**
 * @brief Define type of output of the exception handler. Possible values are
 *        "mail" for sendmail output and "live" for live html output.
 */
if ( !defined('EXCEPTION_HANDLER_OUTPUT') )
{
    define( 'EXCEPTION_HANDLER_OUTPUT', 'live' );
}

/**
 * @brief Mail receiver if EXCEPTION_HANDLER_OUTPUT has the value "mail".
 */
if ( !defined('EXCEPTION_HANDLER_OUTPUT') )
{
    define( 'EXCEPTION_HANDLER_MAIL_RECEIVER', '' );
}

/**
 * @brief Top level handler of exception. Should be registered with set_exception_handler().
 * @param Exception $e The exception to handle.
 */
function exceptionHandler( Exception $e )
{
    $type = 'Exception';
    if ( get_class($e) == 'ErrorException' )
    {
        $type = 'Error';
    }

    switch ( EXCEPTION_HANDLER_OUTPUT )
    {
        case 'live':
        {
            $newline = '<br/>'.PHP_EOL;

            $parameter = '<b>$_GET:</b> ';
            foreach ( $_GET as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }
            $parameter .= $newline;
            $parameter .= '<b>$_POST:</b> ';
            foreach ( $_POST as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }
            $parameter .= $newline;
            $parameter .= '<b>$_COOKIE:</b> ';
            foreach ( $_COOKIE as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }

            $trace = $e->getTrace();
            ob_start();
            var_dump( $trace );
            $verbose = ob_get_clean();
            $verbose = str_replace( ' ', '&nbsp;', $verbose );
            $verbose = nl2br( $verbose );

            $text = '<b>File:</b> '.$e->getFile().$newline.
                    '<b>Line:</b> '.$e->getLine().$newline.
                    '<b>Type:</b> '.$type.$newline.
                    '<b>Message:</b> '.$e->getMessage().$newline.
                    '<b>Url:</b> '.$_SERVER['SERVER_NAME'].
                    $_SERVER['REQUEST_URI'].$newline.
                    $parameter.$newline.$newline.
                    '<b>Stack trace:</b> '.$newline.
                    nl2br( $e->getTraceAsString() ).$newline.$newline.
                    '<b>Stack trace (Verbose):</b> '.$newline.
                    $verbose.$newline;

            echo $text;
        }
        break;

        case 'mail':
        {
            $newline = PHP_EOL;

            $parameter = '$_GET: ';
            foreach ( $_GET as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }
            $parameter .= $newline;
            $parameter .= '$_POST: ';
            foreach ( $_POST as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }
            $parameter .= $newline;
            $parameter .= '$_COOKIE: ';
            foreach ( $_COOKIE as $key => $value )
            {
                $parameter .= $key.' => '.$value.', ';
            }

            $trace = $e->getTrace();
            ob_start();
            var_dump( $trace, true );
            $verbose = ob_get_clean();

            $text = 'File: '.$e->getFile().$newline.
                    'Line: '.$e->getLine().$newline.
                    'Type: '.$type.$newline.
                    'Message: '.$e->getMessage().$newline.
                    'Url: '.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'].$newline.
                    $parameter.$newline.$newline.
                    'Stack trace: '.$newline.
                    $e->getTraceAsString().$newline.$newline.
                    'Stack trace (Verbose): '.$newline.
                    $verbose.$newline;

            if ( !EXCEPTION_HANDLER_MAIL_RECEIVER != '' )
            {
                mail( EXCEPTION_HANDLER_MAIL_RECEIVER, $type, $text );
            }
            else
            {
                echo 'Please set an mail receiver for the exception handler.';
            }
        }
        break;
    }
}

/**
 * @brief Top level handler of errors. Should be registered with set_error_handler().
 * @param int $errno The error number.
 * @param string $errstr The error message.
 * @param string $errfile The file in which the error is occured.
 * @param int $errline The line in which the error is occured.
 */
function errorHandler( $errno, $errstr, $errfile, $errline )
{
    throw new ErrorException( $errstr, 0, $errno, $errfile, $errline );
}
Advertisements