写在前面

  首先,区别 ErrorException 两个概念,这是两个不同的东西。错误是不可忽视的,异常/高级别的错误通常会引起程序停止,而低级别的错误如notice等是可选择忽视的,一般不会造成程序停止运行。当然,个人认为,在不区分语境的情况下,有时出错和出问题可以认为是同一个意思,尽管这两者产生的影响程度上有很大的差别。当我们说到抑错机制的时候,很自然的联想到try-catch接下来说的内容以try-catch的某些方面通过问题的形式展开。

为什么要使用try-catch ?

try-catch 的加入会减少大量 的代码噪音。如何理解噪音?不必要的代码,抑错过度使用。php5-里面因为机制的不完善,须得使用不少的判断语句来减少Error 和 Exception的产生,以便于程序能最大程度的执行到底,诸如 isset(),empty(),is_file(),file_exists.....等等。但是php5里,个人并不建议使用try-catch,至于评价,食之无味,弃之可惜

php的try-catch效果如何?

为什么try-catch强大,评价却褒贬不一,我想这主要还是分版本。

  • 对于php5,如果非要我坦诚,就是两个字,呵呵。说的难听一点,学java学的不到位,高不成低不就,可利用价值不高。因为php5的抑错能力非常有限,Exception必须手动throw才能正常的catch,而对于错误,并没有捕捉的能力。这一点和java、javascript这些语言不同,异常不会自动抛出,自然也不会进入到catch里面。如果定义了set_exception_handler (php5+支持),则可以利用此函数进行所有未捕捉的Exception的处理,但是这也仅仅局限于手动throw的异常,总之,对于错误无可奈何。而在大多数情形下,throw 总是可用return die/exit规避,注意规避并不代表能完全代替;有人会说用set_error_handler,是没错,不过这和try-catch并没有任何关系,而且对于Fatel Error,依然没有任何效果
  • 对于php7,Throwable的加入,使得Error类或Error类的派生类的错误对象产生的大部分Fatel Error都可以像Exception一样正常的被捕获(try-catch/set_error_handler),从这里开始,抑错机制才真正的逐渐完善起来。

演示一个小demo?

假设存在以下代码,在_php-5.6.27_环境下运行

set_exception_handler(function () {
echo "产生了一个异常";
});
set_error_handler(function () {
echo "产生了一个错误";
});
echo $php['test'];
throw new Exception("test", 1);
php();

运行的结果:产生了一个错误 产生了一个异常

这时也许某些人会有疑问,_php()_不存在为什么不报错?前面就说过了,通常异常会引起程序停止,所以php()在之前已经被短路了。

注释掉throw所在行呢?

运行结果: 产生了一个错误 Fatal error: Call to undefined function php()

并不会捕捉Fatal Error.

那么try-catch php()呢

不用想肯定也是这样 Fatal error: Call to undefined function php()

下面是在_7.0.12_下运行的

try {
    echo $php['test'];
    php(); //未定义的函数
} catch (Throwable $e) {
    echo '捕获';
}

运行结果:PHP Notice: Undefined variable: php 捕获

如何合理的运用try-catch或者我需要使用try-catch吗?

当你觉得return/die 能够解决的问题的时候,那就没有必要。当你需要一个健壮的代码层,以便于上级逻辑能够调用并且针对性的处理,比如写一个延展性非常好的mysqli类,或者一个接口的包括代码、错误信息等json,而并非在产生错误时立即停止所有程序,包括调用本层的上级逻辑
也就是说,产生错误的时候,只结束当前层,不结束上层逻辑并抛出信息等待处理,那么try-catch也许是个不错的思路。当然,上面的最后一个例子中,php7环境下还是不会捕捉可忽略的错误,所以,适当的使用set_error_handler和set_exception_handler加持,也许是个非常好的想法。php5里面,如果要使用try-catch,其实要做throw的判断工作和直接return,差不了太多。只是在上层逻辑里面。php是使用is_null / empty/isset等判断还是使用try-catch来加持,这是个值得思考的问题。php7里面,可以考虑直接上重武器了。