有关PHP异常和错误处理机制的思考(二)

通过上篇文章呢,咱们对于PHP异常的定义、捕获、处理等方面有了简单的一个概念,这次呢,咱们就来看下关于异常的同胞兄弟,错误,以及错误的一个处理机制。

我们要知道,PHP中,错误处理,比异常处理,更加重要和凸显价值,咱们之前的文章呢,已经把错误的概念介绍过了,现在,咱们就相比较于异常,来给错误下个最直观的定论,那就是,PHP的错误就是指会使脚本运行不正常的情况。

关于PHP的错误,它有很多种,包括warning,notice,deprecated,fetal error等,这些和一般意义上的错误概念有差别,所以呢,notice不叫通知,而是称为通知级别的错误,同理,warning也不叫警告,它叫警告级别的错误,好啦,废话不多说,我们来看下关于PHP错误的几个类别:

1、deprecated,最低级别的错误,表示“不推荐,不建议”

例如,我们在PHP5中使用ereg系列的正则匹配函数就会报此类错误,这类错误一般是由于使用不推荐,过时的函数或者语法造成的,虽然不影响PHP脚本的正常运行,但是一般情况下,建议修正。

2、notice,指语法中存在不当的地方

就像我们使用变量,但是没有定义的话,就会报此类错误,最常见的就是数组索引是字符时,没有加引号,PHP就把它视作一个常量,先查常量表,找不着再把它视作变量。虽然PHP的脚本对于语法的要求不是很严格,但是仍然建议,对变量进行初始化,这种级别的错误,不影响脚本的正常运行。

3、warning,较高级别错误,指语法中出现很不恰当的情况

例如,参数不匹配,就会报此类错误,这种级别的错误,会导致得不到预期的结果,所以呢,当出现这种级别的错误的时候,就需要我们修改代码了。

4、fetal error,致命错误,导致PHP流程终结,后面代码不执行,需修改代码

5、prase error,最高级别的语法解析错误

上面一到四的错误级别都属于PHP代码运行时的错误,而语法解析错误,就是属于语法检查阶段的错误,这会导致PHP代码无法通过语法检查,而且呢,PHP的错误级别不止上述五个,在手册中,差不多有十六中错误级别,上述错误只是最常用的。

接下来,我们来通过一段代码,来感受下常见的错误级别:

$date = "2018-11-27";
if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})",$date,$reg)) {
    echo $reg[3]."-".$reg[2]."-".$reg[1];
}else{
    echo "error for date";
}

if ($i > 5) {
    echo "un be start";
}

$a = array('o' => 1, 2, 3);
echo $a[o];
echo fun();
echo "致命错误后,是否还会执行?";
//echo "最高级别的错误".$123;

上述代码最少演示了四中错误级别,以及最后注释的最高错误级别,如果我们看不全的话,可以修改配置文件里的error_reporting这个参数的值来查看全部的错误。

说到这个error_reporting了,咱再介绍一个屏蔽错误通知的小技巧,第一,在脚本最顶端加上error_reporting(0)这个东西,就可以屏蔽所有的错误通知,完事第二个就是在容易出现错误的那一行代码的最开始加一个@符号,如@mysqli_connect()。

之后呢,宰门再来看下PHP里的错误处理机制,我们可以使用set_error_handler来接管PHP错误处理,也可以使用trigger_error函数,来主动抛出一个错误。

这个set_error_handler函数主要是用来让用户自定义错误处理函数,需要先创建一个错误处理函数,完事设置错误级别,语法如下:

set_error_handler(error_function,error_types);

参数描述如下:

  1. error_function,规定发生错误时,运行的函数,必需
  2. error_types,规定,在那个错误级别,会显示用户定义的函数,可选,默认为E_ALL

我们如果使用该函数,系统就会完全绕过PHP内部的标准的PHP错误处理函数,如果有必要的话,用户自己定义的错误处理程序,必须要终结(die)脚本的运行。

还有就是,如果是在脚本执行前发生错误,由于在那个时候自定义的程序还没有注册成功,所以就不会用到这个自定义的程序,咱们先来看一个自定义的异常处理函数:

function custonError($errno,$errstr,$errfile,$errline)
{
    echo "错误代码: 【$errno】 $errstr";
    echo "错误所在的代码行:$errline,文件是$errfile";
    echo "PHP的版本 ".PHP_VERSION."(".PHP_OS.")";
}

set_error_handler("custonError",E_ALL|E_STRICT);
$a = array('o' => 1, 2, 3);
echo $a[o];

上述代码中的custonError函数,可以对错误的详情,进行格式化的输出,也可以做任何我们想要做的事情,比如判断当前的环境和权限给出不同的错误提示,我么可以使用error_log函数,将错误记录进入log文件,还可以细致化处理,针对error的不同,进行相对应的处理,不过,我们自定义的错误处理函数一定要有$errno,$errstr,$errfile,$errline这四个输入变量。

erron它是一组常量,代表错误的级别,同时也会有一组整数和其相对应,但是一般使用字符串表示,这样语义会好一点,比如E_WARNING,它的二进制掩码就是4.,表示警告信息。

之后呢,这个custonError函数就会作为回调参数传递给set_error_handler函数,这样一来,就算是接管了PHP原生的错误处理函数了,不过我们要注意的是,这种方式并不能托管所有种类的错误,如E_ERROR,E_PRASE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,以及E_STRICT中的部分,上述这些错误都会以最原始的方式显示错误信息,还有可能不显示错误信息。

set_error_handler函数虽然会接管PHP的错误处理,但是,在同一个页面内,我们可以使用restore_error_handler函数来取消接管,但是注意的是,如果是在接管的状态下,先前使用@屏蔽错误的地方,将会失效,错误会显示。

在PHP的异常中,异常机制的使用是有限的,无法自动抛出异常,只能手动,并且内置的异常很有限,PHP呢,把许多异常看做错误,这样,我们就可以把这些异常来像错误一样,用set_error_handler函数接管,完事主动抛出异常,来看下代码感受下:

function custonError($errno,$errstr,$errfile,$errline)
{
    throw new Exception("$errno | $errstr", 1);
}

set_error_handler("custonError",E_ALL|E_STRICT);

try {
    $a = 5/0;
} catch (Exception $e) {
    echo "错误信息:".$e->getMessage();
}

类似上述代码,我们可以捕获到异常和非致命的错误,在某些方面,弥补了PHP异常处理机制的不足。

这种方式也是有缺陷的,它必须依靠程序员自己来掌控对于异常的处理,对于异常的高发区,敏感区,如果程序员处理不好,就会导致前面所提到的业务数据不一致问题,优点也是很明显,就是可以获取到程序运行时的上下文的信息,可以进行针对性的补救,大概就是这个了。

还有就是这个fetal error错误了,它没有办法捕获,也无法在发生这种错误之后恢复流程处理,但是我们还是可以使用一些特殊的方法对这些错误来进行处理的,这里就是用到了register_shutdown_function这个函数了,它会在PHP程序终结或者die时会触发的一个函数,可以给PHP程序一个短时间的回光返照,在PHP4的时候,类不支持析构函数,所以会用到这函数来模拟实现析构函数的一些作用。

咱们来看段代码感受下register_shutdown_function函数的作用:

class shutDown
{
    
    public function stop()
    {
        if (error_get_last()) {
            var_dump(error_get_last());
        }

        die("stop");
    }
}

register_shutdown_function(array(new shutDown(),'stop'));
$a = new a();
echo "you must be death";

我们对于fetal error错误还可以做点收尾的工作,但是PHP流程的终止,是必然的。

最后就是对于这个prase error错误,咱们就只能看戏了,出了修改PHP的配置文件,就什么都做不了,修改内容如下:

log_error=On
error_log=usr/log/php.log

这样一来,如果出现错误,就会被记录进log文件中,只是可以方便以后的查询。

和异常(exception)类似,错误处理机制有对应的抛出错误的函数,那就是trigger_error函数,示例代码如下:

$a = 0;

if($a==0){
    trigger_error("zero",E_USER_ERROR);
}

echo "stop";

到这里呢,我们有关于异常和错误的介绍和处理也就到此为止了,要注意的是这两个概念是不同的,正是这种设计,从根本上导致了PHP的异常和其他语言的差异,PHP的异常绝大部分必须通过某种方法手动抛出,完事才能捕获到,这是一种半自动化的异常处理机制,总之呢,无论是错误还是异常,都可以使用handler系列函数来接管PHP本身的处理机制。

好啦,本次记录就到这里了。

如果感觉不错的话,请多多点赞支持哦。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值