【问题标题】:Custom Error Handler and Try - Catch - how to handle errors and warnings cleanly自定义错误处理程序和尝试 - 捕获 - 如何干净地处理错误和警告
【发布时间】:2013-11-20 20:52:17
【问题描述】:

我试图更好地理解异常处理。我有一个自定义错误处理程序。在没有邮件服务器的情况下运行以下函数时,它会正确触发错误处理程序并返回“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);
}

【问题讨论】:

    标签: php error-handling try-catch


    【解决方案1】:

    根据定义,如果未捕获异常(或其任何子类),它们将停止程序执行。您可能想要做的是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 块。所以本质上你是trying 来调用反馈函数并且你正在捕获在这样做时可能引发的任何异常。

    在编写良好的代码中,您可能会在大多数用于验证输入的函数/方法代码块的开头附近看到 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 的方法/函数中“提前退出”通常是一种好习惯。换句话说,在可能的情况下,检查所有依赖项并在代码块的开头抛出适当的异常,然后再执行可能执行更改应用程序状态等操作的逻辑。以这种方式预先对异常逻辑进行分组也极大地提高了代码的可读性。

    【讨论】:

    • 哇。我很尴尬地说我从来没有意识到除了set_error_handler之外还有一个set_exception_handler()。我不能轻易地从文档中看出它会产生什么不同。我很欣赏关于使用 try/catch 的说明。在我应该如何使用它的概念上,我似乎已经将功能倒退了。但是...在您的示例中,mail() 在测试if (false === $success) 之前不会抛出异常吗?我的异常处理程序将如何处理它 - 它通常不会抛出异常吗?
    • 如果我的 exception_error_handler 没有抛出一个新的异常,我发现如果我像你一样编写代码,那么我可以在被测试的函数中逐个抛出我自己的异常显示。对吗?
    • @mseifert mail() 不应自行引发异常。即使是这样,它也会被您调用feedback() 周围的try-catch 块捕获。老实说,我不知道您为什么要使用exceptions_error_handler(),因为对我而言,本质上将所有错误都更改为异常并不是一种好的编码习惯。您绝对应该随意在代码中的任何地方抛出异常,只要您觉得自己遇到了预期的用例通常不会产生的情况。
    • @mseifert 这是关于使用自定义异常类型的一个完整的额外策略级别(例如,能够传递给调用客户端,异常本质上是瞬态的,并且应该退出请求,执行自定义日志记录行为等)。但在真正深入研究之前,您可能应该熟悉基本的异常处理。
    • 回应为什么将所有错误都更改为异常:尽管我已经多次看到以这种方式发布的代码,但我确实不使用自定义错误处理程序throw new ErrorException()。我使用异常处理程序来记录所有错误和警告,从而调试我的代码并跟踪运行时问题。我现在才意识到throw new ErrorException() 和try/catch 之间的关系。你的回答应该能让我通过。
    猜你喜欢
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 2010-12-26
    • 2021-07-14
    • 1970-01-01
    • 2017-12-18
    相关资源
    最近更新 更多