php:try-catch 未捕获所有异常

Posted

技术标签:

【中文标题】php:try-catch 未捕获所有异常【英文标题】:php: try-catch not catching all exceptions 【发布时间】:2013-03-05 21:23:44 【问题描述】:

我正在尝试执行以下操作:

try 
    // just an example
    $time      = 'wrong datatype';
    $timestamp = date("Y-m-d H:i:s", $time);
 catch (Exception $e) 
    return false;

// database activity here

简而言之:我初始化了一些要放入数据库的变量。如果由于某种原因初始化失败 - 例如因为 $time 不是预期的格式 - 我希望该方法返回 false 并且不会将错误的数据输入到数据库中。

但是,像这样的错误不会被“catch”语句捕获,而是被全局错误处理程序捕获。 然后脚本继续。

有没有办法解决这个问题?我只是认为这样做会更干净,而不是手动对每个变量进行类型检查,考虑到在 99% 的所有情况下都没有发生任何坏事,这似乎是无效的。

【问题讨论】:

这是因为异常在 php 中没有普遍实现。它们是 PHP5 的补充,很少有内置函数会抛出它们。相反,您需要验证大多数函数的返回值。 【参考方案1】:

解决方案 #1

使用ErrorException将错误转化为异常处理:

function exception_error_handler($errno, $errstr, $errfile, $errline ) 
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);

set_error_handler("exception_error_handler");

解决方案 #2

try 
    // just an example
    $time      = 'wrong datatype';
    if (false === $timestamp = date("Y-m-d H:i:s", $time)) 
        throw new Exception('date error');
    
 catch (Exception $e) 
    return false;

【讨论】:

一些注意事项:1) 如果不希望在整个应用程序中普遍引发异常来代替错误,可以在需要的地方启用此功能,并且可以使用restore_error_handler() 恢复常规错误处理。 2)我希望#2 仍然会发出警告。相同的概念适用:错误报告级别可以使用error_reporting() 更改,然后再更改回来。 无论如何都必须抛出警告。它们是您必须将其保存在某处的信息。不想看就关掉error_display 解决方案#2是Js是怎么做的...如果你知道你在做什么就好了 跟进问题:在您的 MVC 应用程序中使用解决方案 #1 是个好主意吗?我觉得在全球范围内使用它会破坏 Exceptions 的目的,而反复使用 restore_error_handler() 感觉非常hackish。 仅在调试模式@VarunAgrawal,在开发期间。我不会依赖全局 php 设置来正确处理您的应用程序最终将如何运行。【参考方案2】:

我发现的较短的:

set_error_handler(function($errno, $errstr, $errfile, $errline )
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
);

使所有错误成为可捕获ErrorException 的实例

【讨论】:

【参考方案3】:

可以使用catch(Throwable $e) 来捕获所有异常和错误,如下所示:

catch ( Throwable $e)
    $msg = $e->getMessage();

【讨论】:

稍微解释一下就好了。【参考方案4】:
try 
  // call a success/error/progress handler
 catch (\Throwable $e)  // For PHP 7
  // handle $e
 catch (\Exception $e)  // For PHP 5
  // handle $e

【讨论】:

感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请edit您的回答添加一些解释,包括您所做的假设。 @YvetteColomb,哦,所以这是一个消除我意见的幽灵! ;-) 但我仍然相信一些问题可能只有一个单词的答案。问题4 + 4? 的答案是什么 很简短的答案可以不加解释地添加,只有一个字:2,那我们为什么要写:“4 + 4 语句的正确答案是你的问题是2……!”同样,我也同意回复中更详细的解释。但我的意思是,只有其中一些。 我只需要这个简短的答案。但我不确定 4 + 4 = 2。 是的,这是严重缺乏记录的,你几乎不会注意到它,如果你很幸运并同时访问 php.net/manual/en/class.error.php 和 php.net/manual/en/class.exception.php 链接......因为应该包含这个:php.net/manual/en/language.exceptions.php - 甚至不包含单词 Throwable(在文档部分)。 什么情况下会进入后面的catch块?当 Exception 类实现 Throwable 接口时,这不总是在第一个 catch 块中被捕获吗?【参考方案5】:

也可以在catch中为$e参数定义多种类型:

try 
    // just an example
    $time      = 'wrong datatype';
    $timestamp = date("Y-m-d H:i:s", $time);
 catch (Exception|TypeError $e) 
    return false;

【讨论】:

以上是关于php:try-catch 未捕获所有异常的主要内容,如果未能解决你的问题,请参考以下文章

try-catch默认捕获所有异常

在java语言中try-catch的catch中能否再加try--catch?

C#中关于try-catch的异常捕获问题

C#中关于try-catch的异常捕获问题

在 try-catch 块中继续当前迭代 | PHP

无法使用 try-catch 处理 SQL 异常 [重复]