【问题标题】:Zend framework - error page for PHP fatal errorsZend 框架 - PHP 致命错误的错误页面
【发布时间】:2013-04-23 10:46:46
【问题描述】:

在使用 Zend 1 框架的 PHP webapp 上,如果代码抛出异常,我会得到一个带有我的品牌等的漂亮错误页面。

如果代码遇到 PHP 致命错误(例如,当对象引用意外为空时,“方法调用非对象”),那么我只会得到一个 Apache 500 错误页面。

在后一种情况下如何获得漂亮的错误页面?

我尝试过的事情:

  • 如果设置了 PHP ini “display_errors”,那么我只会收到纯文本形式的致命错误消息
  • 如果未设置“display_errors”,则会得到 Apache 默认 500 错误页面
  • 在这种情况下,Apache“ErrorDocument”指令似乎被忽略了

【问题讨论】:

    标签: php zend-framework error-handling fatal-error


    【解决方案1】:

    如果这可以帮助任何人,我可以通过一些技巧获得完整的 Zend 错误页面(带有应用程序布局)以在发生致命错误的情况下显示。

    希望有一种更简单的方法可以做到这一点。如果是这样,请添加您的替代答案。

    将此添加到引导程序:

      /**
       * Sets up a register_shutdown_function hook to give a nice error page when a
       * PHP fatal error is encountered.
       */
      protected function _initFatalErrorCatcher()
      {
          register_shutdown_function(array($this, 'onApplicationShutdown'));
      }
    
      public function onApplicationShutdown()
      {
          $error = error_get_last();
          $wasFatal = ($error && ($error['type'] === E_ERROR) || ($error['type'] === E_USER_ERROR));
          if ($wasFatal)
          {
              $frontController = Zend_Controller_Front::getInstance();
              $errorHandler = $frontController->getPlugin('Zend_Controller_Plugin_ErrorHandler');
              $request = $frontController->getRequest();
              $response = $frontController->getResponse();
    
              // Add the fatal exception to the response in a format that ErrorHandler will understand
              $response->setException(new Exception(
                  "Fatal error: $error[message] at $error[file]:$error[line]",
                  $error['type']));
    
              // Call ErrorHandler->_handleError which will forward to the Error controller
              $handleErrorMethod = new ReflectionMethod('Zend_Controller_Plugin_ErrorHandler', '_handleError');
              $handleErrorMethod->setAccessible(true);
              $handleErrorMethod->invoke($errorHandler, $request);
    
              // Discard any view output from before the fatal
              ob_end_clean();
    
              // Now display the error controller:
              $frontController->dispatch($request, $response);
          }
      }
    

    您需要一个自定义路由器类来提供帮助:

    class My_Router_Rewrite extends Zend_Controller_Router_Rewrite
    {
        public function route(Zend_Controller_Request_Abstract $request)
        {
            // If the ErrorHandler plugin has stashed the error in a request param, then
            // it will have already dealt with routing (see Bootstrap::onApplicationShutdown())
            // (Note that this param cannot be spoofed, since any user-supplied params
            // will be strings, not objects)
            if (is_object($request->getParam('error_handler'))) {
                return $request;
            } else {
                return parent::route($request);
            }
        }
    }
    

    (确保该类在引导程序中注册为您的路由器)

    【讨论】:

    • 这不是你需要的吗?:framework.zend.com/manual/1.12/en/zend.controller.plugins.htmlZend_Controller_Plugin_ErrorHandler 可以很好地处理 500 个错误
    • 不,“Zend_Controller_Plugin_ErrorHandler 提供了一个插入式插件来处理您的应用程序抛出的异常”(我的重点)。我已经有了这个插件(它默认包含在内),它只处理异常。如果没有上面显示的代码,它不会处理致命错误(例如,当对象引用意外为空时,“方法调用非对象”)。
    • 我明白了,但是你的代码不应该出现错误,所以永远不应该看到“漂亮”的错误页面,你应该只在开发过程中得到纯文本错误 :)
    • 大声笑——谁需要错误处理;只要记住不要犯任何错误。
    【解决方案2】:

    一个类似于以前的解决方案,但不需要重写路由器。

    在 Bootstrap.php 中:

    public function __construct($application) {
        parent::__construct($application);
    
        // handle PHP errors
        Core_Error_Handler::set();
    }
    

    Core/Error/Handler.php 类:

    class Core_Error_Handler {
    
        public static function handle() {
    
            if(!$error = error_get_last()) {
                return;
            }
    
            $frontController = Zend_Controller_Front::getInstance();
            $request = $frontController->getRequest();
            $response = $frontController->getResponse();
    
            $response->setException(new Exception("Fatal error: $error[message] at $error[file]:$error[line]",$error['type']));
    
            // this clean what is before the error
            ob_end_clean();
    
            $frontController->dispatch($request, $response);
        }
    
        public static function set(){
            register_shutdown_function(array(__CLASS__, 'handle'));
        }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多