錯誤處理
Yii 提供了一個完整的,基於 PHP5 例外處理的錯誤處理機制。當一個應用程式開始運行,進行使用者請求的處理的時候,會註冊 handleError 方法來處理 PHP warnings 和 notices 訊息;同時也註冊 handleException 方法來處理未被捕獲的 PHP 例外。因此,如果在應用程式運行期間出現一個 PHP warning/notice 或者一個未捕獲的 PHP 例外,錯誤處理器就會接過控制權來運行必要的處理機制。
提示: 錯誤處理器的註冊是在應用程式中的建構器方法中進行的,使用了 PHP 函數set_exception_handler 和 set_error_handler。 如果你不想讓 Yii 來處理錯誤和例外,你可以在入口腳本中定義
YII_ENABLE_ERROR_HANDLER
和YII_ENABLE_EXCEPTION_HANDLER
為false.
預設情況下,在觸發 onError 事件(或onException事件)的時候,errorHandler(或exceptionHandler)將被觸發。如果錯誤或者例外未被任何事件所處理,那麼就需要運行 errorHandler 元件來處理了。
引發例外
在Yii中引發例外和在普通 PHP 檔案中沒什麼兩樣。你可以使用下面的程式碼來拋出例外:
throw new ExceptionClass('錯誤訊息');
Yii定義了兩個例外類別:CException和CHttpException。前者是一個通用的例外類別,而後者用於對最終使用者顯示例外訊息。同時,後者有一個statusCode屬性來代表 HTTP 狀態碼。例外的類型決定了顯示效果,下面會細說。
提示: 想要告訴使用者某個操作是錯誤的,那麼引發一個 CHttpException 例外是最簡單的方法了。比如說,如果使用者在 URL 中提供了一個無效的 ID 值,我們可以顯示一個 404 錯誤:
// 如果提交的 ID 是無效的 throw new CHttpException(404,'此頁面不存在');
顯示錯誤
當一個錯誤被轉發給元件 CErrorHandler 的時候,它會選擇合適的視圖來顯示錯誤。如果這個錯誤要顯示給終端使用者的(比如說一個CHttpException),那麼會使用名為 errorXXX
的視圖來顯示錯誤。這個 XXX
代表著 HTTP 錯誤碼(比如說400,404,500等)。如果這是個內部錯誤,應該只能被開發者看到,那麼將使用的視圖名是 exception
。在第二種中,將會顯示完整的調用堆疊訊息和錯誤行號訊息。
訊息: 當應用程式運行在產品模式時,所有的錯誤,包括內部錯誤都會使用視圖
errorXXX
。這是因為調用的堆疊訊息和錯誤行號訊息可能包含一些敏感訊息。這種情況下,開發者應該依靠錯誤日誌來確定錯誤原因。
CErrorHandler 會搜尋合適的視圖來顯示錯誤訊息,搜尋的順序如下:
WebRoot/themes/ThemeName/views/system
: 在當前主題視圖下的system
目錄中。WebRoot/protected/views/system
: 在應用程式的預設視圖的system
目錄中。yii/framework/views
: 在 Yii 提供的標準視圖目錄中。
因此,如果你想要自定錯誤顯示,可以直接在 system
視圖目錄中或者主題的 system
視圖目錄中建立一個視圖檔案。每個視圖檔案都是一個包含許多 HTML程 式碼的普通 PHP 檔案。參考框架的 view
目錄下的檔案,可以取得更多訊息。
使用一個動作來處理錯誤
Yii也可以使用控制器 動作來處理錯誤顯示。實現的方法是在應用程式的配置檔案中配置一個錯誤處理器。
return array( ...... 'components'=>array( 'errorHandler'=>array( 'errorAction'=>'site/error', ), ), );
上面的程式碼中,我們配置了 CErrorHandler::errorAction 屬性,屬性值是一個路由site/error
。這個路由指向 SiteController
中的 error
。當然,你也可以使用其他的路由。
我們可以這樣來撰寫 error
動作:
public function actionError() { if($error=Yii::app()->errorHandler->error) $this->render('error', $error); }
在這個動作中,首先從 CErrorHandler::error中取得詳細的錯誤訊息。如果取得的訊息非空值,就使用CErrorHandler::error返回的訊息來呈現 error
視圖。CErrorHandler::error返回的訊息是一個陣列,架構如下:
code
: HTTP 狀態碼(比如 403, 500);type
: 錯誤類型(比如 CHttpException,PHP Error
);message
: 錯誤訊息;file
: 發生錯誤的PHP檔案名;line
: 錯誤所在的行號;trace
: 錯誤的調用堆疊訊息;source
: 發生錯誤的程式碼的上下文。
提示: 我們檢查 CErrorHandler::error 是否為空值的原因是
error
動作可以被使用者存取,這時候也許並沒有什麼錯誤。當我們傳遞$error
陣列給視圖,它將會被自動釋放為獨立的變數。所以,在視圖中我們可以使用$code
和$type
來存取這些訊息。
訊息記錄
一個 error
級別的錯誤訊息會在錯誤發生時候被記錄。如果這個錯誤是由 PHP warning 或 notice 引發的,那麼這個訊息將會被記錄在 php
這個分類中;如果錯誤訊息是由未捕獲的例外所引起的,那麼分類將是 exception.ExceptionClassName
(對於 CHttpException 來說,它的 statusCode 也將被追加到分類中)。開發者可以使用這些記錄來監測應用程式執行時候的錯誤訊息