当抛出异常并在找到解决方案的地方冒泡时,我们如何将控件发送回抛出异常的地方


When an exception is thrown and bubble up where a solution is found, how can we send the control back to where the exception was thrown?

为了具体化,我提供了一些代码,我知道,在这些代码中,我想要的是不可能的。我正在寻找另一种方法来获得同样的结果。

<?php
  error_reporting(E_ALL | E_STRICT); 
  function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    // When $errno is a notice, we would like a way for the execution to continue here. Since it is only a notice, eventually it could go back to where the notice was triggered. 
  }
  set_error_handler("exception_error_handler");
  Class TopLevelManagement {
    private $genericInfo = "Very important to add in notices"; 
    function highleveljob() {
      try{
        // In practice, the following statements could occur below in the execution tree, after a few other function calls. 
        $specific = new SpecificAndEncapsulated();
        $specific->specificjob();
      }
      catch (ErrorException $e) {
        $message = $e->getMessage() . $this->genericInfo; 
        mail($admin_email, "Consider the generic info and recover from this situation", $message); 
        // Here we would like the execution to continue where the exception was thrown. In the real world, this would be like "thank you error handler for SpecificAndEncapsulated::specificjob, we have taken care of the issue with the help of our larger perspective.". 
      }   
    } 
  }
  Class SpecificAndEncapsulated {
    function specificjob() {
      // Some processing
      if($unexpected == true) trigger_error('Here is how little I know, as I should', E_USER_NOTICE);
      // Continue as expected after a notice.
    }
  }
?>

当然,一种解决方案是将$genericInfo作为参数或全局变量传递给SpecificAndEncapsulated::justdomyjob,并让error_handler在不引发任何异常的情况下处理该问题。然而,这种解决方案并不自然。还有其他方法可以系统地将变量$genericInfo传递给SpecificAndEncapsulated,但问题是一样的。不需要系统地传递$genericInfo值,因为它不应该涉及SpecificAndEncapsulated,即使在发生异常时也不应该,更不用说在每次调用时系统地传递了。在更高级别管理通知后,回复异常发布者说"谢谢,现在继续"是很自然的。是否支持这种类型的E_NOTICE或E_USER_NOTICE管理?

根据设计,异常是正常执行无法继续的错误。

在现实世界中,情况会是这样的:一名警察(第三方)打电话给卡车运输公司调度员(顶级代码),说"你的一辆卡车在火球中爆炸,司机在医院"(这份工作),调度员说"注意到了。我希望有效载荷能如期到达。"

如果要继续作业,则必须捕获作业内部的异常。一种可行的方法是将错误处理程序函数或委托对象传递到作业中。

PHP5有一个类似于其他编程语言的异常模型。可以在PHP中抛出和捕获("catched")异常。代码可以被包围在try块中,以便于捕获潜在的异常。每次尝试必须至少有一个相应的catch块。可以使用多个catch块来捕获不同类别的异常。在序列中定义的最后一个catch块之后,正常执行(当try块内没有抛出异常,或者不存在与抛出异常的类匹配的catch时)将继续。异常可以在catch块中抛出(或重新抛出)。

当抛出异常时,语句后面的代码将不会执行,PHP将尝试查找第一个匹配的catch块。如果没有捕捉到异常,则会发出PHP致命错误,并显示"Uncaught exception…"消息,除非使用set_exception_handler()定义了处理程序。

在PHP5.5及更高版本中,还可以在catch块之后指定finally块。finally块中的代码将始终在try-and-catch块之后执行,无论是否引发异常,并且在恢复正常执行之前执行。

抛出的对象必须是Exception类的实例或Exception的子类。尝试抛出一个不是的对象将导致PHP致命错误。