【问题标题】:php: catch exception and continue execution, is it possible?php:捕获异常并继续执行,有可能吗?
【发布时间】:2010-01-25 14:07:28
【问题描述】:

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

【问题讨论】:

    标签: php


    【解决方案1】:

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

    例如

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

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

    只将这些东西放入相互依赖的try 块中。例如。 b 取决于 a 的某些结果,将 b 放在 try-catch 块之后是没有意义的。

    【讨论】:

    • 我代表你做了 :)
    • $e 必须是\Exception $e 否则会抛出解析错误
    • 这个解释太棒了
    • 直截了当的解释。应该再次强调,在大多数情况下,在catch 内部做一些有意义的事情很重要。否则代码就会中断,可能很难辨别原因。
    • c() 如果现在 catch 块内有 throw 将被执行,否则代码将被停止
    【解决方案2】:

    当然,只要捕获你想继续执行的异常...

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

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

    【讨论】:

    • 如果我可以补充:在 catch 块中不做任何事情就捕获异常被认为是不好的风格,您至少应该写一些日志输出(或者,如示例中那样,提供注释 真的,真的,真的什么都不需要做)。如果您使用 catch(Exception $ex) {} 捕获 any 异常,则尤其如此
    • 那么你如何记录它并仍然继续?
    • 最佳实践是使用:Try -> Catch (handle Exception) -> finally (finally 总是运行) 可能我的想法有误,但还是想给你一些意见。跨度>
    • 是否有一种内置的方式(或约定)可以明确地说“什么也不做”,例如pass 在 Python 中?
    • 重要提示:如果您在代码中输入一行:[condition or die("whatever")] try-catch 不起作用,立即终止程序。它有逻辑......在你调试代码之后
    【解决方案3】:

    当然:

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

    您可能想阅读Exceptions 上的 PHP 文档。

    【讨论】:

    • 这将抛出一个新的异常,该异常现在被 try 块捕获,导致未捕获的异常
    • @JakeN 不正确。由于抛出的异常被catch 块捕获,因此它永远不会导致未捕获的异常。
    • 我现在已经阅读了我的评论。而且我真的不知道我的意思!
    • @JakeN try 块不能catch 异常。
    【解决方案4】:

    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.
    

    【讨论】:

    • 如果你告诉某人“使用”某物,也要告诉对方“为什么”。为什么ThrowableException 好?
    • 这救了我的培根——我正在调用作曲家所需的一个类的函数,而后者又调用了另一个函数,如果该函数产生错误则没有捕捉到——所以无论如何,有一个try catch 链中的间隙。我将代码更改为 Throwable 并且无论如何它都捕获了它,因为某种原因 \Exception 不会捕获。
    • 异常可能被捕获,并且被称为在其他地方被吞下。像这个例子。这意味着任何下游都不会知道失败。 Throwable 是一个级别,因此执行此操作的旧代码可能不会吞噬所有内容。它可以作为一种称为隔板的模式很有用,但也习惯性地包含一个记录器依赖项并输出某种形式的有关失败的有用消息以及您是否会恢复。
    • @DanielW。因为 Exception 实现了 Throwable;在 php >7 中,如果抛出错误 catch 块中的异常不会捕获它,但 Throwable 会
    【解决方案5】:

    是的。

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

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

    @myfunction();
    

    【讨论】:

      【解决方案6】:

      对于 PHP 8+,我们可以省略捕获异常的变量名。

      catch

      从 PHP 8.0.0 开始,捕获异常的变量名是可选的。如果未指定,catch 块仍将执行,但无权访问抛出的对象。

      因此我们可以这样做:

      try {
        throw new Exception("An error");
      }
      catch (Exception) {}
      

      【讨论】:

        【解决方案7】:

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

        我需要使用我正在编写的模板框架来执行此操作。如果用户试图访问数据中不存在的属性,我会返回处理函数内部的错误,而不是抛出它。

        然后,在调用代码中,我可以决定是抛出这个返回的错误,导致 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() 之前与该对象进行比较,但无论如何您都可以重新抛出错误,并且如果您完全控制整体结构,我认为这是解决无法继续尝试/捕获问题的一种巧妙方法。

        【讨论】:

          【解决方案8】:

          一个老问题,但是我过去从 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() 是否在每次迭代中工作或出错。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-02-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多