2013-04-29 53 views
1

在使用Zend框架1,如果代碼拋出一個異常,我得到一個不錯的錯誤頁面,我的品牌等Zend框架 - PHP的致命錯誤的錯誤頁面

一個PHP Web應用程序如果代碼遇到一個PHP致命錯誤(例如,當對象引用意外爲空時,「對非對象進行方法調用」),那麼我只會得到一個純粹的Apache 500錯誤頁面。

如何在後一種情況下獲得好的錯誤頁面?

事情我已經嘗試:

  • 如果PHP的ini「的display_errors」設置,然後我得到公正的致命錯誤消息以純文本格式
  • 如果沒有設置「display_errors設置」,然後我得到Apache的默認的500錯誤頁面
  • 阿帕奇「的ErrorDocument」指令,似乎在這種情況下被忽略

回答

2

如果這可以幫助任何人,我能,通過一點兩輪牛車的,得到充分的Zend錯誤PAG e(帶應用程序佈局)在發生致命錯誤時顯示。

希望有一個更簡單的方法來做到這一點。如果是這樣,請在您的替代方案中添加一個答案。

一下添加到引導:

/** 
    * 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); 
     } 
    } 
} 

(確保這個類是在引導註冊爲你的路由器)

+0

不這樣做,你需要什麼?:HTTP://framework.zend。 COM /手動/ 1.12/EN/zend.controller.plugins.html。 'Zend_Controller_Plugin_ErrorHandler'處理錯誤500錯誤 – Ashley 2013-04-30 21:04:08

+0

不,「Zend_Controller_Plugin_ErrorHandler提供了一個用於處理應用程序拋出的**異常**的插件」(我強調)。我已經有了這個插件(默認包含它),它只處理異常。沒有上面顯示的代碼,它不會處理致命錯誤(例如,當對象引用意外爲空時,「在非對象上調用方法」)。 – Rich 2013-05-01 10:11:03

+1

我看到了,但是你的代碼不應該與錯誤一起上線,所以「好的」錯誤頁面不應該被看到,你應該只在開發過程中得到純文本錯誤:) – Ashley 2013-05-01 12:25:24

1

類似於以前的解決方案,但不需要重寫路由器。

在bootstrap.php中:

public function __construct($application) { 
    parent::__construct($application); 

    // handle PHP errors 
    Core_Error_Handler::set(); 
} 

核心/錯誤/ 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')); 
    } 
}