【发布时间】:2010-01-25 14:07:28
【问题描述】:
是否可以捕获异常并继续执行脚本?
【问题讨论】:
标签: php
是否可以捕获异常并继续执行脚本?
【问题讨论】:
标签: php
是的,但这取决于您要执行的操作:
例如
try {
a();
b();
}
catch(Exception $e){
}
c();
c() 将始终被执行。但如果a() 抛出异常,b() 将不执行。
只将这些东西放入相互依赖的try 块中。例如。 b 取决于 a 的某些结果,将 b 放在 try-catch 块之后是没有意义的。
【讨论】:
$e 必须是\Exception $e 否则会抛出解析错误
catch 内部做一些有意义的事情很重要。否则代码就会中断,可能很难辨别原因。
当然,只要捕获你想继续执行的异常...
try
{
SomeOperation();
}
catch (SomeException $e)
{
// do nothing... php will ignore and continue
}
当然,这存在静默删除可能是非常重要的错误的问题。 SomeOperation() 可能会失败,从而导致其他微妙的、难以解决的问题,但你永远不会知道你是否默默地放弃了异常。
【讨论】:
pass 在 Python 中?
当然:
try {
throw new Exception('Something bad');
} catch (Exception $e) {
// Do nothing
}
您可能想阅读Exceptions 上的 PHP 文档。
【讨论】:
catch 块捕获,因此它永远不会导致未捕获的异常。
使用新的Throwable接口
try {
// Code that may throw an Exception or Error.
} catch (Throwable $t) {
// Handle exception
}
echo "Script is still running..."; // this script will be executed.
【讨论】:
Throwable 比Exception 好?
是的。
try {
Somecode();
catch (Exception $e) {
// handle or ignore exception here.
}
但是请注意,php 也有与异常分开的错误代码,这是 php 具有 oop 原语之前的遗留问题。大多数内置库仍然会引发错误代码,而不是异常。要忽略错误代码,请调用以@为前缀的函数:
@myfunction();
【讨论】:
对于 PHP 8+,我们可以省略捕获异常的变量名。
从 PHP 8.0.0 开始,捕获异常的变量名是可选的。如果未指定,catch 块仍将执行,但无权访问抛出的对象。
因此我们可以这样做:
try {
throw new Exception("An error");
}
catch (Exception) {}
【讨论】:
另一个角度是从处理代码中返回一个异常,而不是抛出一个异常。
我需要使用我正在编写的模板框架来执行此操作。如果用户试图访问数据中不存在的属性,我会返回处理函数内部的错误,而不是抛出它。
然后,在调用代码中,我可以决定是抛出这个返回的错误,导致 try() 捕获(),还是继续:
// process the template
try
{
// this function will pass back a value, or a TemplateExecption if invalid
$result = $this->process($value);
// if the result is an error, choose what to do with it
if($result instanceof TemplateExecption)
{
if(DEBUGGING == TRUE)
{
throw($result); // throw the original error
}
else
{
$result = NULL; // ignore the error
}
}
}
// catch TemplateExceptions
catch(TemplateException $e)
{
// handle template exceptions
}
// catch normal PHP Exceptions
catch(Exception $e)
{
// handle normal exceptions
}
// if we get here, $result was valid, or ignored
return $result;
这样做的结果是我仍然得到原始错误的上下文,即使它被抛出在顶部。
另一种选择可能是返回自定义 NullObject 或 UnknownProperty 对象并在决定触发 catch() 之前与该对象进行比较,但无论如何您都可以重新抛出错误,并且如果您完全控制整体结构,我认为这是解决无法继续尝试/捕获问题的一种巧妙方法。
【讨论】:
一个老问题,但是我过去从 VBA scipts 转到 php 时遇到的一个问题,您可以在其中“转到”以使用“恢复”重新进入“错误”循环,然后它就静止了处理函数。
在 php 中,经过一些试验和错误,我现在使用嵌套的 try{} catch{} 来处理关键与非关键进程,甚至用于相互依赖的类调用,这样我就可以追溯到错误的开始。
例如如果函数 b 依赖于函数 a,但函数 c 很好,但不应停止该过程,并且无论如何我仍然想知道所有 3 个的结果,这就是我所做的:
//set up array to capture output of all 3 functions
$resultArr = array(array(), array(), array());
// Loop through the primary array and run the functions
foreach($x as $key => $val)
{
try
{
$resultArr[$key][0][] = a($key);
$resultArr[$key][1][] = b($val);
try
{ // If successful, output of c() is captured
$resultArr[$key][2][] = c($key, $val);
}
catch(Exception $ex)
{ // If an error, capture why c() failed
$resultArr[$key][2][] = $ex->getMessage();
}
}
catch(Exception $ex)
{ // If critical functions a() or b() fail, we catch the reason why
$criticalError = $ex->getMessage();
}
}
现在我可以遍历每个键的结果数组并评估结果。
如果 a() 或 b() 出现严重故障。
在 $resultArr 中发生严重故障之前,我仍然有一个参考点,如果异常处理程序设置正确,我知道是 a() 还是 b() 失败了。
如果 c() 失败,循环继续。如果 c() 在各个点都失败了,通过一些额外的循环后逻辑,我什至可以通过询问 $resultArr[$key][2] 来确定 c() 是否在每次迭代中工作或出错。
【讨论】: