当前位置: 首页 > 知识库问答 >
问题:

请问php异常处理为何无效?

冷英博
2023-08-16

image.png
输出结果如下
image.png

共有2个答案

柯易安
2023-08-16

很久很久以前,PHP只有Error没有Exception,PHP5才引入Exception的异常概念,可以手动throw让try/catch捕获

所以在PHP5时代,你有两个选择处理这个Warning错误

  1. 开发环境通过php.ini配置直接显示,而不需要try/catch手动处理,这样简单粗暴方便调试,而在开发阶段没发现的,带到了生产环境,则配置记录错误,有问题了通过错误日志去查,然后修复这个错误
  2. 主动判断并手动抛出异常,让try/catch捕获,如下
<?php$a = 1;$b = 0;try{    if($b==0){        throw new Exception("手动抛出异常,0不能作为除数");    }    $result = $a / $b;}catch(Exception $e){    var_dump($e);}

输出结果

object(Exception)#1 (7) {  ["message":protected]=>  string(40) "手动抛出异常,0不能作为除数"  ["string":"Exception":private]=>  string(0) ""  ["code":protected]=>  int(0)  ["file":protected]=>  string(28) "/Users/charles/Desktop/b.php"  ["line":protected]=>  int(6)  ["trace":"Exception":private]=>  array(0) {  }  ["previous":"Exception":private]=>  NULL}

而在PHP7时代,引入了全新的Throwable来处理Error和Exception,因为Error和Exception都继承自Throwable,所以Throwable终于可以同时处理错误和异常,示例代码如下

<?phptry{    $result = 1 / 0;}catch(Throwable $t){    var_dump($t);}

输出结果

object(DivisionByZeroError)#1 (7) {  ["message":protected]=>  string(16) "Division by zero"  ["string":"Error":private]=>  string(0) ""  ["code":protected]=>  int(0)  ["file":protected]=>  string(28) "/Users/charles/Desktop/a.php"  ["line":protected]=>  int(4)  ["trace":"Error":private]=>  array(0) {  }  ["previous":"Error":private]=>  NULL}
董飞航
2023-08-16

简单的说,因为这个在这里目前是一个 Warning 而不是一个 Exception。

而 Warning 属于 Error 的一部分,虽然 PHP 7 错误处理 的介绍中提到了。

PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在 大多数错误被作为 Error 异常抛出。

没错,只是大多数的被作为 Error 异常抛出了,但是除零这种情况并不包含在内(其实还有很多情况都不会转为异常抛出)。

其他答主已经介绍过, PHP 7 开始 Throwable 可以捕获来自 Error 的异常并进行处理。

image.png

看到上图,你应该注意到了 DivisionByZeroError 这一个属于错误下的类,但是如果你在 PHP 7 版本中运行这段代码。

<?phptry{    $result = 1 / 0;}catch(Throwable $t){    var_dump($t);}

你就会发现,也并没有捕获到这个异常,满头问号吧 ❓❓❓。

好吧,在 PHP 7 中,只是将 %(取模)在模 0 的时候会触发 DivisionByZeroError 这个异常类。不信你把上面代码改一下。

<?phptry{    $result = 1 % 0;}catch(Throwable $t){    var_dump($t);}

你会发现,现在就可以捕获到这个 DivisionByZeroError 异常了。

那,就没有办法来处理这个 Error 了吗?

当然可以,要在 PHP 7 及以前的版本中处理这个可以使用 set_error_handler 这个函数,来注册一个错误处理函数,这样当发生错误时,就会把错信息传递到这个函数来。

你可以在这个函数中什么也不做(那么将当作无事发生,代码将继续运行)

<?phpset_error_handler(function () {    var_dump('发生错误啦!');});try {    $result = 1 / 0;    var_dump('我会显示。');} catch (Throwable $t) {    var_dump('我不会显示。');}var_dump('可以运行到这里喔');

上面的代码则会打印:

发生错误啦!我会显示。可以运行到这里喔!

你可以在这个处理函数中抛出一个异常,这样你就能在 catch 里面捕获到了。

<?phpset_error_handler(function ($code, $msg) {    throw new DivisionByZeroError($msg, $code);});try {    $result = 1 / 0;    var_dump('我不会显示!');} catch (Throwable $t) {    var_dump('捕获到啦!');}var_dump('我会显示!');

上面的代码将会一次打印

捕获到啦!我会显示!

但,自 PHP 8 起,PHP RFC: Reclassifying engine warnings 这个 RFC 通过后,除零也改为了抛出 DivisionByZeroError 异常,所以,自 PHP 8 开始,你就可以直接捕获到这个异常了。

  • 查看示例
 类似资料:
  • 问题内容: 我有一个关于异常处理的问题。考虑以下Java代码段。 我知道这是处理异常的推荐方法。但是我可以通过使用以下代码片段来实现相同的目的。 有人可以告诉我第二种方法的弊端吗? 问题答案: 第二种方法可读性较差。此外,即使“聪明”的窍门是使用instanceof关键字,Pokemon异常处理也永远不会走。无论如何,我不是在取笑或嘲笑您,但最好是编写供人类阅读和维护的代码,而不是计算机。

  • 本文向大家介绍PHP异常处理Exception类,包括了PHP异常处理Exception类的使用技巧和注意事项,需要的朋友参考一下 异常(Exception)用于在指定的错误发生时改变脚本的正常流程。 什么是异常? PHP 5 提供了一种新的面向对象的错误处理方法。 异常处理用于在指定的错误(异常)情况发生时改变脚本的正常流程。这种情况称为异常。 当异常被触发时,通常会发生: 当前代码状态被保存

  • 我对Java硒有问题。我用它来自动化测试web页面,它的结构非常复杂--大量的元素是动态加载的,html页面中有大量不必要的元素。要使我的测试可靠是很难的。有时页面不能加载,或者我尝试点击还不存在的按钮(当然是类似的方法)。 于是,我用下面这样的方法编写了Util类: 我知道它看起来很糟糕,我还没有重构它,但是method通常在大多数情况下工作良好--在第二个或第三个循环中输入字段被填充。 首先,

  • 当我尝试连接到Oracle数据库时,出现了以下问题。 有例外 此reportMapper.xml

  • 问题内容: 我的问题很简短。我不明白为什么我的程序在捕获错误时会无限循环。我做了一个新的try- catch语句,但是它循环了,甚至复制,粘贴并修改了以前有效的程序中的适当变量。下面是语句本身,下面是整个程序。谢谢您的帮助! 程序: 问题答案: 您的程序将永远运行,因为在不更改扫描仪状态的情况下进行调用会一次又一次地引发异常:如果用户未输入,则调用不会更改扫描仪的外观,因此,当您在下一次迭代中进行

  • 我不知道该怎么办。 当我试图从解析器获取语法错误的数量时,它显示0。 编辑: 它返回null。