在生产服务器上格式化 PHP 错误


Format PHP error on production server

我的生产计算机上有自定义错误处理程序:

register_shutdown_function( "check_for_fatal" );
set_error_handler('errHandle');
set_exception_handler( "log_exception" );

所有错误都将发送到邮件。但是格式很糟糕(直线文本)。

有没有人知道任何库、函数、拥有任何代码,这些代码会在 html 中格式化错误,并提供尽可能多的细节。(消息,文件,行,错误类,完整的调用堆栈,也许是全局变量 - $_GET,$_POST,...尽可能多的信息,所以我将更容易解决问题。

<?php
    // Defining the handlers.
    register_shutdown_function( 'FatalErrorHandler' );
    set_error_handler(          'ErrorHandler'      );
    function ErrorHandler( $iNumber, $sMessage, $sFile, $sLine, array $aContext )
    {
        $aLastError = error_get_last();
        // If we have a fatal error let the fatal handler take care of it.
        // Required otherwise dual logs will occur as both handlers are called.
        if ( $aLastError === NULL )
        {
            $aError = array();
            $aError[ 'error' ][ 'code'    ] = $iNumber;
            $aError[ 'error' ][ 'msg'     ] = $sMessage;
            $aError[ 'error' ][ 'file'    ] = $sFile;
            $aError[ 'error' ][ 'line'    ] = $sLine;
            $aError[ 'error' ][ 'context' ] = $aContext;
            // Remove output.
            ob_clean();
            $sOutputMsg = 'Error ''' . $iNumber . ''' occurred in ' . $sFile .
                ' on line ' . $sLine . ' Message: ' . $sMessage;
            $sTrace = '';
            $aTrace = debug_backtrace();
            $iCountTraces = count( $aTrace );
            for( $i = 0; $i < $iCountTraces; ++$i )
            {
                $sTrace .= '<h3>Trace '
                    . $i
                    . '</h3><div><pre>'
                    . print_r( $aTrace[ $i ], true )
                    . '</pre></div>';
            }
            $sFullMessage = '<div id="top">'
                . $sOutputMsg
                . '<br />Error: '
                . $iNumber
                . '<br />File: '
                . $sFile
                . '<br />Line: '
                . $sLine
                . '<br />'
                . $sMessage
                . '<br/ ></div><div id="trace">Context: <pre>'
                . print_r( $aContext, true )
                . '</pre><br / >Stacktrace: '
                . '<br />'
                . $sTrace;
            var_dump( $sFullMessage );
            // Log( $sFullMessage );
        }
    }
    function FatalErrorHandler()
    {
        $aLastError = error_get_last();
        // Ensure this is a fatal error otherwise let errorhandler handle it.
        if ( ( $aLastError[ 'type' ] === E_ERROR ) || ( $aLastError[ 'type' ] === E_USER_ERROR ) )
        {
            // Remove output.
            ob_clean();
            // Ensure we had data inside error get last.
            $sType = empty( $aLastError[ 'type' ] ) ? '' : $aLastError[ 'type' ];
            $sFile = empty( $aLastError[ 'file' ] ) ? '' : $aLastError[ 'file' ];
            $sLine = empty( $aLastError[ 'line' ] ) ? '' : $aLastError[ 'line' ];
            $sMsg  = empty( $aLastError[ 'msg' ]  ) ? '' : $aLastError[ 'msg' ];
            $sFullMessage = 'Fatal Error '''
                . $sType
                . ''' occurred in '
                . $sFile
                . ' on line '
                . $sLine
                . '<br />Message: '
                . $sMsg;
            // Fatal errors don't have a stacktrace.
            var_dump( $sFullMessage );
            // Log( $sFullMessage );
        }
    }
    // Examples:
    // Fatal error throw
    $oTmp = NULL;
    $oTmp->hey();
    // Error throw
    // e
?>

我也自己做。由于我处理了很多PDO,因此我还检查异常是否为PDO并添加一些详细信息。

输出并不漂亮,但它是为开发人员而不是其他人准备的。

static function FormatException($exception, $level = 0)
        {
            $result = "";
            $result = sprintf('<div style="padding-left:%dpx">', $level * 20);
            $result .= sprintf("<div><b>Message: </b> %s</div>", $exception->getMessage());
            $result .= sprintf("<div><b>Code: </b> %s</div>", $exception->getCode());
            $result .= sprintf("<div><b>File: </b> %s</div>", $exception->getFile());
            $result .= sprintf("<div><b>Line: </b> %s</div>", $exception->getLine());
            $result .= sprintf("<div><b>Trace: </b></div>");
            $result .= sprintf('<div style="padding-left: 20px;">');
            foreach ($exception->getTrace() as $trace)
            {
                $result .= sprintf('<div style="border: 1px solid #000;margin-top: 10px;">');
                $result .= sprintf("<div><b>File: </b> %s</div>", $trace['file']);
                $result .= sprintf("<div><b>Line: </b> %s</div>", $trace['line']);
                $result .= sprintf("<div><b>Function: </b> %s</div>", $trace['function']);
                $result .= sprintf("<div><b>Class: </b> %s</div>", $trace['class']);
                $result .= sprintf("<div><b>Type: </b> %s</div>", $trace['type']);
                $result .= sprintf("<div><b>Args: </b></div>");
                $result .= sprintf('<div style="padding-left: 20px;">');
                foreach ($trace['args'] as $arg)
                    $result .= sprintf("<div><b>Arg: </b>%s</div>", json_encode($arg));
                $result .= sprintf("</div>");
                $result .= sprintf("</div>");
            }
            $result .= sprintf("</div>");
            if (get_class($exception) === "PDOException")
            {
                $result .= sprintf("<br />");
                $result .= sprintf("<div><b>PDO: </b></div>");
                $result .= sprintf('<div style="padding-left: 20px;">');
                $result .= sprintf("<div><b>Code: </b> %s</div>", $exception->errorInfo[0]);
                $result .= sprintf("<div><b>Driver code: </b> %s</div>", $exception->errorInfo[1]);
                $result .= sprintf("<div><b>Message: </b> %s</div>", $exception->errorInfo[2]);
                $result .= sprintf("</div>");
            }
            $prev = $exception->getPrevious();
            if (isset($prev))
                $result .= self::FormatException($prev, $level++);
            $result .= sprintf("</div>");
            $result .= sprintf("<br />");
            return $result;
        }