php:捕获异常并继续执行,这可能吗?


75

是否可以捕获异常并继续执行脚本?

Answers:


102

当然,只要在要继续执行的地方捕获异常即可。

  try
  {
      SomeOperation();
  }
  catch (SomeException $e)
  {
      // do nothing... php will ignore and continue    
  }

当然,这存在静默删除可能是非常重要的错误的问题。SomeOperation()可能会失败,从而导致其他难以解决的细微问题,但是您永远不会知道是否静默删除该异常。


7
如果我可能要添加:在catch块中不执行任何操作而捕获异常被认为是不好的样式,则至少应编写一些日志输出(或者,如示例中那样,提供注释,说明确实没有任何事情要做) )。如果赶上这是尤其如此,任何与赶上(例外$ EX)异常{}
Morfildur

2
那么您如何记录它并仍然继续?
数值

2
最佳实践是使用:尝试->捕获(异常处理)->最终(最终总是在其中运行)可能是您的想法错了,但仍然想给您一些输入。
Bram B

是否有内置的方式(或约定)来明确地表示“不执行任何操作”(例如pass在Python中)?
cprn

重要提示:如果在代码中添加以下行:[condition or die(“ whatever”)] try-catch不起作用,请立即终止程序。它具有逻辑...调试代码后
Grenville Tryon '18

133

是的,但这取决于您要执行的操作:

例如

try {
   a();
   b();
}
catch(Exception $e){
}

c();

c()将始终被执行。但是如果a()抛出异常,b()不会执行。

只能将内容放入相互依赖的try模块中。例如,b取决于某些结果,将a其放在btry-catch块之后没有任何意义。


我代表您做了:)
Christian M. Raymonds,2015年

2
$e需要为\Exception $e或类似或将引发解析错误
iautomation

真棒的解释
Thejas

简单的解释。再次需要强调的是,在大多数情况下,必须在内进行有意义的操作catch。否则,代码只会中断,可能很难分辨原因。
MQuiggGeorgia

如果现在在catch块中有抛出,则将执行c(),否则代码将停止
hendra1

17

当然:

try {
   throw new Exception('Something bad');
} catch (Exception $e) {
    // Do nothing
}

您可能需要阅读有关Exceptions的PHP文档。


这将引发一个新的异常,该异常现在已被try块捕获,从而导致未捕获的异常
Jake N

1
@JakeN不正确。由于抛出的异常是由catch块捕获的,因此它永远不会导致未捕获的异常。
佩雷

2
我已经阅读了我的评论。我真的不知道我的意思!
杰克·N

@JakeN try块无法捕获异常。
Ejaz

6

是。

try {
    Somecode();
catch (Exception $e) {
    // handle or ignore exception here. 
}

但是请注意,php还具有与异常分开的错误代码,这是php具有oop原语之前的传统保留。大多数库内置函数仍会引发错误代码,而不是异常。要忽略错误代码,请调用以@开头的函数:

@myfunction();

5

PHP> 7

使用新的界面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.

2
如果您告诉某人“使用”某物,也请告诉“为什么”。为什么Throwable优于Exception
Daniel W.

0

另一个角度是从处理代码中返回一个异常,而不是抛出异常。

我需要使用我正在编写的模板框架来做到这一点。如果用户尝试访问数据上不存在的属性,那么我将从处理功能的更深处返回错误,而不是抛出错误。

然后,在调用代码中,我可以决定是抛出此返回的错误,使try()成为catch(),还是继续:

// 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()之前与之进行比较,但是由于您仍然可以重新引发错误,并且如果您完全控制了整个结构,我认为这是解决无法继续尝试/捕获问题的巧妙方法。


0

一个古老的问题,但是我过去从VBA scipts转到php时曾遇到过一个问题,您可以在其中使用“ GoTo”以“ Resume”重新进入循环“ On Error”,然后它仍在处理该函数。
在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()在每次迭代中是否有效或有错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.