3.PHP自定义错误处理器

1. 使用set_error_handler 自定义错误处理函数说明

  • 1.创建错误处理函数
  • 2.设置不同级别调用函数
  • 3.set_error_handler函数指定接管错误处理

set_error_handler 说明

mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )
设置一个用户的函数(error_handler)来处理脚本中出现的错误。

本函数可以用你自己定义的方式来处理运行中的错误, 例如,在应用程序中严重错误发生时,或者在特定条件下触发了一个错误(使用 trigger_error()),你需要对数据/文件做清理回收。

重要的是要记住 error_types 里指定的错误类型都会绕过 PHP 标准错误处理程序, 除非回调函数返回了 FALSE。 error_reporting() 设置将不会起到作用而你的错误处理函数继续会被调用 —— 不过你仍然可以获取 error_reporting 的当前值,并做适当处理。 需要特别注意的是带 @ error-control operator 前缀的语句发生错误时,这个值会是 0。

同时注意,在需要时你有责任使用 die()。 如果错误处理程序返回了,脚本将会继续执行发生错误的后一行。

以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。

如果错误发生在脚本执行之前(比如文件上传时),将不会 调用自定义的错误处理程序因为它尚未在那时注册。

参数

error_handler
用户的函数需要接受两个参数:错误码和描述错误的 string。 另外有可能提供三个可选参数:发生错误的文件名、发生错误的行号 以及发生错误的上下文(一个指向错误发生时活动符号表的 array)。 该函数可以表示为:

handler ( int $errno , string $errstr [, string $errfile [, int $errline [, array $errcontext ]]] )
errno
第一个参数 errno,包含了错误的级别,是一个 integer。
errstr
第二个参数 errstr,包含了错误的信息,是一个 string。
errfile
第三个参数是可选的,errfile, 包含了发生错误的文件名,是一个 string。
errline
第四个参数是一个可选项, errline, 包含了错误发生的行号,是一个 integer。
errcontext
第五个可选参数, errcontext, 是一个指向错误发生时活动符号表的 array。 也就是说,errcontext 会包含错误触发处作用域内所有变量的数组。 用户的错误处理程序不应该修改错误上下文(context)。
如果函数返回 FALSE,标准错误处理处理程序将会继续调用。

error_types
就像error_reporting 的 ini 设置能够控制错误的显示一样, 此参数能够用于屏蔽 error_handler 的触发。 如果没有该掩码, 无论 error_reporting 是如何设置的, error_handler 都会在每个错误发生时被调用。

2. set_error_handler的使用

header('content-type:text/html; charset=utf-8');
//开启所有的错误报告
error_reporting(-1);
function customError($errno, $errmsg, $errfile, $errline){
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

    switch ($errno) {
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errmsg<br />".PHP_EOL;
        echo "  Fatal error on line $errline in file $errfile";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />".PHP_EOL;
        echo "Aborting...<br />\n";
        // exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errmsg<br />".PHP_EOL;
        break;

    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errmsg<br />".PHP_EOL;
        break;

    default:
        echo "Unknown error type: [$errno] $errmsg<br />".PHP_EOL;
        break;
    }

    /* Don't execute PHP internal error handler */
    return true;
}
set_error_handler('customError');
echo $test;
settype($var, 'king');
// test();
trigger_error('出错了!', E_USER_ERROR);
echo '<hr>';
//回收错误接管
restore_error_handler();
echo $king;
echo '<hr>';
set_error_handler('customError', E_ALL&~E_NOTICE);
echo '<hr>';
settype($var, 'king');
echo 'continue...............';

3.自定义错误处理类

/**
 * 自定义错误处理类
 */
class MyErrorHandler
{
    public $msg='';
    public $filename='';
    public $line=0;
    public $vars=array();
    protected $_noticeLog = '/tmp/php_error.log';

    function __construct($msg, $filename, $line, $vars)
    {
        $this->msg=$msg;
        $this->filename=$filename;
        $this->line=$line;
        $this->vars=$vars;
    }

    /**
     * [deal 自定义错误处理请求]
     * @param  [int] $errno   [错误号]
     * @param  [string] $errmsg  [错误描述]
     * @param  [string] $errfile [出错的文件]
     * @param  [int] $errline [出错的行号]
     * @param  [array] $vars    [错误触发处作用域内所有变量的数组]
     * @return [bool]          
     */
    public static function deal($errno, $errmsg, $errfile, $errline, $vars){
        $self = new self($errmsg, $errfile, $errline, $vars);

        switch ($errno) {
            //致命级别的错误发邮件给管理员
            case E_USER_ERROR:
                return $self->dealError();
                break;

            case E_USER_WARNING:
            case E_WARNING:
                return $self->dealWarning();
                break;

            case E_USER_NOTICE:
            case E_NOTICE:
                return $self->dealNotice();
                break;

            default:
                //交给php本身的错误机制处理
                return false;
                break;
        }
    }

    public function get_debug_print_backtrace($traces_to_ignore = 1){
        $traces = debug_backtrace();
        $ret = array();
        foreach($traces as $i => $call){
            if ($i < $traces_to_ignore ) {
                continue;
            }

            $object = '';
            if (isset($call['class'])) {
                $object = $call['class'].$call['type'];
                if (is_array($call['args'])) {
                    foreach ($call['args'] as &$arg) {
                        $this->get_arg($arg);
                    }
                }
            }        

            $ret[] = '#'.str_pad($i - $traces_to_ignore, 3, ' ')
            .$object.$call['function'].'('.implode(', ', $call['args'])
            .') called at ['.$call['file'].':'.$call['line'].']';
        }

        return implode("\n",$ret);
    }

    public function get_arg(&$arg) {
        if (is_object($arg)) {
            $arr = (array)$arg;
            $args = array();
            foreach($arr as $key => $value) {
                if (strpos($key, chr(0)) !== false) {
                    $key = '';    // Private variable found
                }
                $args[] =  '['.$key.'] => '.get_arg($value);
            }

            $arg = get_class($arg) . ' Object ('.implode(',', $args).')';
        }
    }

    /**
     * [dealError 处理错误级别的错误]
     * @return [type] [description]
     */
    public function dealError(){
        $backtrace=$this->get_debug_print_backtrace();
        echo $backtrace; exit;
        $errorMsg=<<<EOF
        出现了致命错误,如下
产生错误的文件:{$this->filename}
产生错误的信息:{$this->msg}
产生错误的行号:{$this->line}
追踪信息:{$backtrace}
\n
EOF;
        error_log($errorMsg, 1, '732578448@qq.com');
        exit(1);
    }

    /**
     * [dealWarning 处理警告级别的错误]
     * @return [bool]
     */
    public function dealWarning(){
        $errorMsg=<<<EOF
        出现了警告错误,如下
产生警告的文件:{$this->filename}
产生警告的信息:{$this->msg}
产生警告的行号:{$this->line}
\n
EOF;
        error_log($errorMsg, 1, '732578448@qq.com');
    }

    /**
     * [dealNotice 处理通知级别的错误]
     * @return bool
     */
    public function dealNotice(){
        $datetime = date('Y-m-d H:i:s', time());
        $errorMsg=<<<EOF
        出现了通知错误,如下
产生通知的文件:{$this->filename}
产生通知的信息:{$this->msg}
产生通知的行号:{$this->line}
产生通知的时间:{$datetime}
\n
EOF;
        return error_log($errorMsg, 3, $this->_noticeLog);
    }
}


error_reporting(-1);
set_error_handler(array('MyErrorHandler', 'deal'));
ini_set('display_errors', 0);
echo $var;
trigger_error('zhiming', E_USER_ERROR);
trigger_error('zhiming', E_USER_WARNING);

4.register_shutdown_function函数的使用

1.作用

1.通过register_shutdown_function函数,可以让我们设置一个当执行关闭时可以被调用的另一个函数。
2.当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会被调用

2.使用场景

1.页面强制被停止
2.程序代码意外终止或超时

3.注意点

1.在register_shutdown_function之前不能有die() exit()等终止函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值