自定义错误处理程序和Try-Catch-如何干净地处理错误和警告


Custom Error Handler and Try - Catch - how to handle errors and warnings cleanly

我正在努力更好地理解异常处理。我有一个自定义错误处理程序。当以下函数在没有邮件服务器的情况下运行时,它会正确地触发错误处理程序并返回"Tough Luck"。在错误处理程序中,我必须使用throw new ErrorException()才能激活try/catch。如果没有此语句,错误发生后,程序将继续执行下一行代码(在本例中返回"Feedback left")。

能够继续下一行代码是有用的,因为用户不会收到刺耳的错误消息和警告。但是,我希望能够在选定的情况下使用Try/Catch。

在用户看不到错误但我可以使用try/catch的情况下,有什么更好的方法来处理错误?有没有办法抛出新的ErrorException(使用$e->getSeverity()?)如果存在try/catch,则在哪里进行处理,但如果没有,则忽略异常?

set_error_handler('exceptions_error_handler');
error_reporting(E_ALL ^ E_STRICT);
echo feedback();
function feedback(){
    try{
        mail("m@localhost","subject","body","From: me");
        return "Feedback left.";
    }
    catch(Exception $e){
        error_log("Error sending feedback email." . "Some Custom Info For Error Log");
        return "Tough Luck";
    }
}

function exceptions_error_handler( $errno, $errmsg, $errfile, $errline, $context = null ){
    // custom log file handling
    log_exception( new ErrorException( $errmsg, 0, $errno, $errfile, $errline) );
    // required in order for the try/catch to be activated
    throw new ErrorException($errmsg, 0, $errno, $errfile, $errline);
}

根据定义,如果没有捕获到异常(或其任何子类),它们将停止程序执行。您可能想要做的是set_exception_handler()能够处理代码中可能发生的任何未捕获的异常。

一般来说,您需要决定处理异常和错误的策略。对于大多数人来说,当应用程序进入意外状态(例如没有邮件服务器、失去数据库连接等)时,会引发异常。错误可能会导致你进入这种状态,或者在你进入这种情况时被触发,但不一定会导致您潜在地改变应用程序的行为方式(比如提前终止请求)。

举个例子,对于你的情况,我可能会考虑这样的东西:

try {
   echo feedback();
} catch(Exception $e) {
   echo 'Feedback failed with exception: ' . $e->message;
}
function feedback() {
   $success = mail(...);
   if (false === $success) {
        $error_info = error_get_last();
        throw new Exception('Mail failed with error: ' . $error_info['message']);
   } else {
       return 'Feedback Left';
   }
}

通常,您可能会将try-catch块封装在类方法调用的单个函数周围,而不是尝试在函数本身中创建try-catch区块。因此,从本质上讲,您是try正在调用反馈函数,并且您正在捕获在这样做时可能引发的任何异常

在编写良好的代码中,您可能会在大多数用于验证输入的函数/方法代码块的开头附近看到throw,因为输入无效会表明应用程序处于意外状态。所以类似于:

public function set_foo($bar = NULL) {
    if(is_null($bar)) {
        throw new Exception('A value must be passed for $bar');
    }
    // perform method logic
}

通常,从抛出Expcetion的方法/函数中"提前退出"是一种很好的做法。换句话说,在可能的情况下,在执行可能更改应用程序状态之类的逻辑之前,检查所有依赖项,并在代码块的开头抛出适当的Exception。以这种方式将异常逻辑提前分组,也大大有助于提高代码的可读性。