当抛出异常并在找到解决方案的地方冒泡时,我们如何才能将控件发送回抛出异常的地方?
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
,即使发生异常时也不应该,甚至在每次调用时更不用说。在更高级别管理通知后,返回异常发出者的通信说 "thanks, now continue" 是很自然的。是否支持这种类型的 E_NOTICE 或 E_USER_NOTICE 管理?
异常,按照设计,是错误之后无法继续正常执行。
在现实世界中,它会是这样的:一名警官(第三方)打电话给货运公司调度员(顶级代码)并说,"one of your trucks exploded in a ball of fire and the driver is in the hospital"(工作),然后调度员说 "Noted. I expect the payload to arrive on schedule."
如果你想继续工作,你必须在工作中捕获异常。一种可行的方法是将错误处理函数或委托对象传递到作业中。
PHP 5 有一个类似于其他编程语言的异常模型。可以抛出异常,并在 PHP 内捕获 ("catched")。代码可能包含在 try 块中,以便于捕获潜在的异常。每个 try 必须至少有一个对应的 catch 块。多个 catch 块可用于捕获不同的 classes 异常。正常执行(当 try 块中没有抛出异常时,或者当匹配抛出异常的 class 的 catch 不存在时)将在按顺序定义的最后一个 catch 块之后继续。可以在 catch 块中抛出(或重新抛出)异常。
当抛出异常时,语句后面的代码将不会被执行,并且PHP将尝试找到第一个匹配的catch块。如果未捕获异常,将发出 PHP 致命错误和 "Uncaught Exception ..." 消息,除非已使用 set_exception_handler().
定义处理程序
在 PHP 5.5 及更高版本中,也可以在 catch 块之后指定 finally 块。 finally 块中的代码将始终在 try 和 catch 块之后执行,无论是否抛出异常,并且在恢复正常执行之前。
抛出的对象必须是 Exception class 的实例或 Exception 的子class。尝试抛出一个不是的对象将导致 PHP 致命错误。
为了具体起见,我提供了一些代码,据我所知,其中我想要的是不可能的。我正在寻找另一种方法来获得相同的东西。
<?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
,即使发生异常时也不应该,甚至在每次调用时更不用说。在更高级别管理通知后,返回异常发出者的通信说 "thanks, now continue" 是很自然的。是否支持这种类型的 E_NOTICE 或 E_USER_NOTICE 管理?
异常,按照设计,是错误之后无法继续正常执行。
在现实世界中,它会是这样的:一名警官(第三方)打电话给货运公司调度员(顶级代码)并说,"one of your trucks exploded in a ball of fire and the driver is in the hospital"(工作),然后调度员说 "Noted. I expect the payload to arrive on schedule."
如果你想继续工作,你必须在工作中捕获异常。一种可行的方法是将错误处理函数或委托对象传递到作业中。
PHP 5 有一个类似于其他编程语言的异常模型。可以抛出异常,并在 PHP 内捕获 ("catched")。代码可能包含在 try 块中,以便于捕获潜在的异常。每个 try 必须至少有一个对应的 catch 块。多个 catch 块可用于捕获不同的 classes 异常。正常执行(当 try 块中没有抛出异常时,或者当匹配抛出异常的 class 的 catch 不存在时)将在按顺序定义的最后一个 catch 块之后继续。可以在 catch 块中抛出(或重新抛出)异常。
当抛出异常时,语句后面的代码将不会被执行,并且PHP将尝试找到第一个匹配的catch块。如果未捕获异常,将发出 PHP 致命错误和 "Uncaught Exception ..." 消息,除非已使用 set_exception_handler().
定义处理程序在 PHP 5.5 及更高版本中,也可以在 catch 块之后指定 finally 块。 finally 块中的代码将始终在 try 和 catch 块之后执行,无论是否抛出异常,并且在恢复正常执行之前。
抛出的对象必须是 Exception class 的实例或 Exception 的子class。尝试抛出一个不是的对象将导致 PHP 致命错误。