php的错误注册处理函数

背景:

以前看tp的相关源码,有一段错误处理函数逻辑,看了下里面的源码,针对错误处理,大概有以下几个函数。

  • set_error_handler — 设置用户自定义的错误处理函数

本函数可以用你自己定义的方式来处理运行中的错误, 例如,在应用程序中严重错误发生时,或者在特定条件下触发了一个错误(使用 trigger_error()),你可以在处理函数做一些日志记录功能,这个处理函数能处理一些像notic,waring,人为触发错误等,像falter error,parse error是没有效果的。

注意:如果错误发生在脚本执行之前,将不会调用自定义的错误处理程序因为它尚未在那时注册

 

  • set_exception_handler — 设置用户自定义的异常处理函数

当一个未捕获的异常发生时所调用函数的名称,用于没有用 try/catch 块来捕获的异常。 在 exception_handler 调用后异常会中止

  • register_shutdown_function — 注册一个会在php中止时执行的函数

常用于在注册一个导致php中止的致命错误的处理函数,像falter error,parse error等。

通过自己做的一些尝试,发现了一些在错误处理函数上需要注意的地方,上代码。

文件一   app.php

<?php
class App{
    public function __construct()
    {
        $this->error();
    }

    public function error()
    {
        set_error_handler([$this,'_error_handler']);
        set_exception_handler([$this,'_exception_handler']);
        register_shutdown_function([$this,'_error_register']);
    }

    //记录日志
    public function errlog($type,$msg,$file,$line)
    {
        $time = date('Y-m-d H:i:s')."\r\n";
        $type = '错误代码:'.$type."\r\n";
        $msg = '错误信息:'.$msg."\r\n";
        $file = '错误文件:'.$file."\r\n";
        $line = '错误行数:'.$line."\r\n\r\n";
        error_log($time.$type.$msg.$file.$line,3,str_replace('\\', '/', __dir__).'/error.log');
    }
    
    //异常处理函数
    public function _exception_handler(Throwable $exception)
    {
        if($exception instanceof Exception){

        }elseif ($exception instanceof Error) {
            
        }
        $this->errlog($exception->getCode(),$exception->getMessage(),$exception->getFile(),$exception->getLine());
    }
    

    //错误处理函数
    public function _error_handler($errno, $errstr, $errfile, $errline)
    {
        $this->errlog($errno,$errstr,$errfile,$errline);
    }
    
    //在php中止时执行的函数
    public function _error_register()
    {
        if($err = error_get_last()){
            $this->errlog($err['type'],$err['message'],$err['file'],$err['line']);
        }
    }

}



if(defined('DEBUG')){//开发模式
    error_reporting(E_ALL);
}else{
    error_reporting(0);
}


$app = new App();
//模拟各种错误的文件
require 'err_include.php';

文件二 err_include.php

<?php
//error_reporting(0);
foobar(3, 5);//Fatal error级别的错误,在当前页面关闭错误报告并且注册了php中止时执行的函数(register_shutdown_function)的情况下,仍然会爆出错误并且不会运行中止注册函数

/*
Parse error级别的错误,在当前页面关闭错误报告并且注册了php中止时执行的函数(register_shutdown_function)的情况下,
仍然会爆出错误并且不会运行中止注册函数
可以在另一个页面引入出现致命错误的页面,然后
*/
var_dump(23+-+);

// notice级别的错误,在当前页面关闭错误报告并且了注册错误处理函数(set_error_handler)的情况下,不会爆出错误,与falter error,parse error不同
echo $foo['bar'];    

//人为触发错误,在当前页面关闭错误报告并且注册了错误处理函数(set_error_handler)的情况下,不会爆出错误,并且会运行注册的处理函数,与falter error,parse error不同
 trigger_error('人为触发一个错误', E_USER_ERROR); 

//模拟产生Warning 错误,与上面类似

include 'xyz.php';

//抛出异常,在当前页面关闭错误报告并且注册了异常处理函数(_exception_handler)的情况下,不会爆出错误,并且会运行注册的处理函数

throw new Exception('This is a exception', 400);

 

总结:

  • 当捕获处理致命错误、编译错误时,会发现在致命错误、编译错误当前的页面是无法捕获的,并且无法关闭错误报告,需要到另一个没有致命错误的页面通过包含错误页面然后捕获
  • err_log()这个函数,必须写绝对文件路径,不然会写不进文件
posted @ 2018-05-04 16:52  rcj_飞翔  阅读(284)  评论(0)    收藏  举报