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, ‘[email protected]‘);
        exit(1);
    }

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

    /**
     * [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()等终止函数

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-13 01:33:23

3.PHP自定义错误处理器的相关文章

PHP学习笔记三十三【自定义错误处理器】

<?php //自定义错误处理器 //$errorno 错误号 //$errmes错误信息 //这两个参数是必须的 function my_error($errorno,$errmes) { echo "<font size='5' color='red'>$errorno</font><br/>"; echo "错误信息是:$errmes"; } //必须重写set_error_handler处理器 set_error_h

PHP 错误与异常 笔记与总结(9)自定义错误处理器

自定义错误处理器更加智能. <?php class myErrorHandler{ //$message:错误信息 //$filename:错误文件名 //$line:错误行号 //$vars:额外信息 public $message = ''; public $filename = ''; public $line = 0; public $vars = array(); protected $_noticeLog = 'D:\practise\php\From\notice\noticeLo

自定义错误处理器

什么叫错误处理器? 就是一旦发生错误,用来处理该错误的一种"机器" --其实就是一个函数. 自定义错误处理,就是指: 让系统不要去处理错误,而完全由我们(开发者)来对错误处理:显示和记录. 做法,其实很简单,就两步: 第一步: 设定要用于处理错误的函数名! set_error_handler("f1"); 第二步: 去定义该函数 function f1() { //这里可以任意写代码:自然正常是去显示错误报告和记录错误日志. } 代码: <?php //第一步

错误处理器、错误触发器

[错误级别] 2 E_WARNING:非致命的run-time错误.不暂停脚本执行. 8 E_NOTICE:Run-time通知.脚本发现可能有错误发生,但也可能在脚本正常运行时发生. 256 E_USER_ERROR:致命的用户生成的错误.trigger_error()设置的E_ERROR. 512 E_USER_WARNING:非致命的用户生成的警告.trigger_error()设置的E_WARNING. 1024 E_USER_NOTICE:用户生成的通知.trigger_error()

Laravel之加密解密/日志/异常处理及自定义错误

一.加密解密 1.加密Crypt::encrypt($request->secret) 2.解密try { $decrypted = Crypt::decrypt($encryptedValue);} catch (DecryptException $e) { //} 二.日志 1.配置文件config/app.php 中的debug 配置选项控制浏览器显示的错误详情数量.默认情况下,该配置选项被设置在.env 文件中的环境变量APP_DEBUG .对本地开发而言,你应该设置环境变量APP_DE

MVC4 自定义错误页面(三)

一.概述 MVC4框架自带了定义错误页,该页面位于Shared/Error,该页面能够显示系统未能捕获的异常,如何才能使用该页面: 二.使用步骤: 1.配置WebConfig文件,在System.Web节点下加上 <customErrors mode="On"  defaultRedirect="~/Shared/Error" /> 翻阅一些大神写的博客,在他们的博客中指出defaultRedirect是指向错误页面的URL,可是经过本人测试的时候,发现

ASP.NET全局错误处理和异常日志记录以及IIS配置自定义错误页面

应用场景和使用目的 很多时候,我们在访问页面的时候,由于程序异常.系统崩溃会导致出现黄页.在通常的情况下,黄页对于我们来说,帮助是极大的,因为它可以帮助我们知道问题根源,甚至是哪一行代码出现了错误.但这对于用户是非常可怕的,因为用户不知道发生了什么,也无法了解黄页给出的内容.甚至,如果我们遇到一些不友好的人,他们会拿这些内容大做文章,对我们网站产生威胁. 那我们如何在程序异常.系统崩溃时,不会出现黄页,并且还可以给出一些更加友好的提示呢?甚至在我们需要的时候,可以收集这些异常信息,并加以分析,能

PHP 错误与异常 笔记与总结(8)自定义错误处理函数 set_error_handler()

通过 Set_error_handler() 函数设置用户自定义的错误处理函数. 步骤: ① 创建错误处理函数 ② 设置不同级别调用函数 ③ Set_error_handler() 函数制定接管错误处理—— 如果使用了该函数,程序会绕过标准的 PHP 错误处理. 摘自:php.net mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] ) 设置一个用户的函数(erro

简单的php自定义错误日志

平时经常看php的错误日志,很少有机会去自己动手写日志,看了王健的<最佳日志实践>觉得写一个清晰明了,结构分明的日志还是非常有必要的. 在写日志前,我们问问自己:为什么我们有时要记录自定义的日志呢?而不用系统默认的日志记录方式呢? 我认为有两个原因: 1.团队需要一个统一格式的日志方便管理 2.大量无用错误日志占据硬盘空间,仅需记录有意义的日志. 那么,实践一下. 1.打开你的php.ini 2.打开日志记录,将 log_errors = Off 改成 log_errors = On 3.将p