【问题标题】:PHP exception handler and shutdown functionPHP 异常处理程序和关闭函数
【发布时间】:2014-08-21 20:58:12
【问题描述】:

如何捕获我在自定义关闭函数中抛出的(自定义)异常(使用自定义异常处理程序)?我没有使用任何框架。

例子:

register_shutdown_function( 'shutdownFunction');
set_exception_handler(      'exceptionHandler');

function exceptionHandler(Exception $exception)
{
    // handle and log exception for later debugging...
}

function shutdownFunction()
{
    // something is not going right...
    if (someVariable != someValue)
        throw new RuntimeException('blah...'); // WILL NOT be caught by exception handler
}



// somewhere else in the code...
throw new Exception('something...'); // WILL be caught by exception handler (but not in shutdown function)

脚本正在使用异常来传达它在执行期间遇到的错误,即。意外变量传递给函数,数据库无法插入行等...

【问题讨论】:

  • 任何未捕获的异常现在都将转到exceptionHandler 并结束终止 PHP 应用程序。您无法从未捕获的异常中恢复。您可以使用 try...catch 块捕获错误

标签: php exception-handling


【解决方案1】:

你可以用

包裹你的shutdownFunction的主体
function shutdownFunction()
    try {
        ...
    } catch (\Exception $e) {
        // do something
    }
}

您将捕获所有异常,因为 Exception 是所有异常的基类

【讨论】:

  • 我的意思是我有一个文件,其中包含异常和错误处理和日志记录,每次用户访问任何页面时它都会包含在主脚本中。通过在失败的语句中抛出异常来控制应用程序流。在关闭函数之前,一切都很完美,因为 PHP 已经(不知何故,不知道)注销了我的异常处理程序,如果我从现在开始抛出任何异常,它将不再被调用。
  • 这种拦截PHP错误信息/异常的方法似乎效果不错,只是它没有被充实。经过更多测试后,我将发布我的版本作为答案。这种拦截取决于它在哪里完成;在这种情况下,它是在关闭功能中完成的,其中挑战是独一无二的。设计一个简单但可靠的错误日志记录系统来替代 PHP 错误和异常处理并且还可以在各种上下文中处理应用程序检测到的错误是一项艰巨的工作。
【解决方案2】:

你根本无法在 php 中做到这一点。

register_shutdown_function 回调是 PHP 应用程序中发生的最后一件事。试图在那里抛出异常只会调用标准的 php 处理程序。在网络上找不到太多关于这些内部工作原理的信息。

但是,我创建了自己的解决方案,将其定向到单个函数。

set_exception_handlerregister_shutdown_function 是非常不同的功能:

  • set_exception_handler 接收单个参数 Exception
  • register_shutdown_function 默认不接收任何参数

我已经让set_exception_handler(接收$exception 作为参数)设置了一个我可以在register_shutdown_function 中使用的属性。

$lastException = null;

set_exception_handler(function ($e) use (&$lastException) {
    $lastException = $e;
});

register_shutdown_function(function() use(&$lastException) {
    if($error = error_get_last()) {
        $lastException = new \ErrorException($error['message'], $error['type'], 1, $error['file'], $error['line']);
    }
    if($lastException) {
        if (APPLICATION_ENV === 'production') {
            Sentry\captureException($lastException);
        } else {
            var_dump($lastException);
        }
    }
});

我不知道这是否是解决问题的好方法,但它允许我在同一函数中捕获 require unexisting_phpfile1389.php 错误(致命)和常规 throw \Exception()s。

试图在关闭处理程序中抛出异常将导致以下异常(多么讽刺):

( ! ) 致命错误:未捕获错误:只能将对象扔进 C:...\index.php 第 34 行

( ! ) 错误:只能将对象扔进 C:...\index.php 第 34 行

【讨论】:

    【解决方案3】:

    很简单:

    function exception_handler (Exception $e) {
    
      if ($e instanceof DBException)
        error_handler (['query' => $e->getQuery ()]); // Your actions with your custom Exception object
      
    }
    
    function error_handler ($error) {
    
      if (isset ($error['query']))
          echo $error['query'];
      else
         // Another errors
      
    }
    
    set_error_handler ('error_handler', E_ALL);
    set_exception_handler ('exception_handler');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 2020-03-22
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多