執行個體講解如何在PHP的Yii架構中進行錯誤和異常處理,執行個體講解yii
Yii已經預設已經在CApplication上實現了異常和錯誤的接管,這是通過php的set_exception_handler,set_error_handler實現的。通過這兩個PHP內建函數,可以對程式中未捕獲的異常以及錯誤進行接管處理,從而提高程式的可維護性。這在大型系統是至關重要的,當發生錯誤時,我們希望能將相關詳細資料記錄,甚至是即時發送警示,從而縮短損毀修復時間,提高整個系統的穩定性。
預設情況下,Yii會將異常處理分配給CApplication::handleException, 將錯誤處理分配給CApplication::handleError,但是可以通過在入口檔案中定義YII_ENABLE_EXCEPTION_HANDLER, YII_ENABLE_ERROR_HANDLER兩個常量為false禁止使用Yii的異常和錯誤接管機制。
以下內容中,將異常和錯誤統稱為錯誤,如有必要會進行詳細區分說明。YII_DEBUG常量(預設為false, 可以在入口檔案中設定)對錯誤資訊的顯示有很重要的影響,debug模式下,錯誤的輸出是最詳細的。而程式一旦投入運行,則應將YII_DEBUG修改為false。
無論是否處於debug模式,Yii程式產生錯誤時均會將相關錯誤資訊進行記錄(錯誤層級為error, 分類預設為application)。不同之處是debug模式時會直接在web頁上顯示詳細資料。
CApplication:: handleError($code,$message,$file,$line)
上面的方法實現了相關邏。特別注意restore_error_handler,restore_exception_handler兩個函數,如果沒有這兩個函數的調用,那麼在後續的錯誤處理過程中,當再次產生異常或是錯誤時,又會調用CApplication:: handleError ,從而可能造成死迴圈,故Yii在此處臨時禁止了使用CApplication:: handleError 接管後續的錯誤和異常(使用php預設的錯誤處理機制),這就保證了不會因之產生迴圈調用。
PHP錯誤的處理當產生錯誤時,PHP會在日誌中記錄哪些資訊?錯誤碼(即PHP的E_ERROR E_WARNING E_STRICT E_DEPRECATED)訊息內容(如 Undefined vaiable $input)產生錯誤的檔案路徑產生錯誤的行號額外的跟蹤回溯資訊(這是通過debug_backtrace實現的)當前URL
除了記錄相應日誌之外,Yii還會對錯誤進行後續處理(如中斷運行、顯示錯誤頁等),預設情況下錯誤的處理會交給CErrorHandler組件處理(但可以通過給CApplicaton綁定onError事件處理器而實現錯誤處理的二次接管,此處的設計很靈活!)。
此時將產生一個CErrorEvent(並包含$code,$message,$file,$line幾項關鍵參數),傳遞給CErrorHandler組件進行處理。具體是交給CErrorHandler::handleError處理之。這個流程主要是將錯誤相關資訊進行整理,並以合適的方式進行顯示。
是否為debug模式(YII_DEBUG==true),對錯誤資訊的顯示結果有極大影響。偵錯模式下我們希望能顯示詳細的錯誤跟蹤資訊,而在生產模式下,我們希望給使用者顯示友好的頁面。所以,此處的錯誤顯示有所不同,下面區分說明之。
當處於偵錯模式時,將直接渲染exception視圖展示錯誤。將按以下路徑搜尋:
- protected/views/system/exception.php
- YII_PATH/views/exception.php
顯然,預設情況下並沒有在應用程式中定義views/system目錄,故會使用系統架構內建的視圖檔案。最終包含的檔案將是Yii架構中的views/exception.php。
從以上分析中可以得知,在偵錯模式下如果我們要使用自訂異常頁面(一般這麼做的意義可能不大),則需要設定檔protected/views/system/exception.php, 可使用的變數即$data。
當處於非偵錯模式下時,會作如下處理:
設定檔中若為errorHandler組件定義了errorAction路由資訊,則直接運行之,否則執行第2步流程。
嘗試載入error視圖,按以下路徑搜尋(第一個搜尋到的檔案將被使用)
- protected/views/system/zh_cn/error500.php
- protected/views/system/error500.php
- protected/views/system/zh_cn/error.php
- protected/views/system/error.php
- YII_PATH/views/zh_cn/error500.php
- YII_PATH/views/error500.php
- YII_PATH/views/zh_cn/error.php
- Y II_PATH/views/error.php
異常的處理根據前面的分析,異常的處理機制與錯誤處理機制類似,也會記錄日誌,層級是error, 分類為"exception.$EXCEPTIONCLASS", 若是CHttpException類異常,分類名稱則為exception.CHttpException.$STATUS_CODE。如資料的異常分類稱為exception.CDbException。
接下來將錯誤事件CExceptionEvent交由errorHandler處理,所有錯誤資訊都由CExceptionEvent對象傳遞而來。處理方法如下:
如果是偵錯模式,則按以下順序搜尋視圖檔案,第一個搜尋到的檔案將被使用
- protected/views/system/exception.php
- YII_PATH/views/exception.php
如果是非偵錯模式,並在設定檔中為errorHandler組件定義了errorAction屬性路由,則運行之,否則進入第3步。
按以下順序嘗試載入視圖檔案,第一個搜尋到的檔案將被使用
protected/views/system/zh_cn/error500.phpprotected/views/system/error500.phpprotected/views/system/zh_cn/error.phpprotected/views/system/error.phpYII_PATH/views/zh_cn/error500.phpYII_PATH/views/error500.phpYII_PATH/views/zh_cn/error.phpY II_PATH/views/error.php
使用流程圖描述,會更清楚一些:搜尋視圖檔案流程比較重要,因為它關係到我們如何自訂錯誤頁面的細節問題,後續的流程圖詳細描述其過程。
可以看出,最容易的方式還是給errorHandler組件設定errorAction屬性指定錯誤發生的路由
一般而言,我們最關心的是生產模式下錯誤頁面的顯示問題,經過以上分析,有兩種方法可用:
設定檔中為errorHandler組件定義errorAction路由屬性(應該優先使用這個方式,以達到靈活配置目的)
定義以下檔案中的任意一個,實現自訂錯誤頁(不推薦)
- Protected/views/system/zh_cn/error500.php
- protected/views/system/error500.php
- protected/views/system/zh_cn/error.php
- protected/views/system/error.php
第1種方式靈活可控,可以在控制器中指定視圖檔案,靈活可控。
使用錯誤處理器樣本
yii\web\ErrorHandler 註冊成一個名稱為errorHandler應用組件, 可以在應用配置中配置它類似如下:
return [ 'components' => [ 'errorHandler' => [ 'maxSourceLines' => 20, ], ],];
使用如上代碼,異常頁面最多顯示20條原始碼。
如前所述,錯誤處理器將所有非致命PHP錯誤轉換成可擷取異常,也就是說可以使用如下代碼處理PHP錯誤:
use Yii;use yii\base\ErrorException;try { 10/0;} catch (ErrorException $e) { Yii::warning("Division by zero.");}// execution continues...
如果你想顯示一個錯誤頁面告訴使用者請求是無效的或無法處理的,可簡單地拋出一個 yii\web\HttpException異常, 如 yii\web\NotFoundHttpException。錯誤處理器會正確地設定響應的HTTP狀態代碼並使用合適的錯誤視圖頁面來顯示錯誤資訊。
use yii\web\NotFoundHttpException;throw new NotFoundHttpException();
自訂錯誤顯示
yii\web\ErrorHandler錯誤處理器根據常量YII_DEBUG的值來調整錯誤顯示, 當YII_DEBUG 為 true (表示在偵錯模式),錯誤處理器會顯示異常以及詳細的函數調用棧和原始碼行數來協助調試, 當YII_DEBUG 為 false,只有錯誤資訊會被顯示以防止應用的敏感資訊洩漏。
補充: 如果異常是繼承 yii\base\UserException,不管YII_DEBUG為何值,函數調用棧資訊都不會顯示, 這是因為這種錯誤會被認為是使用者產生的錯誤,開發人員不需要去修正。
yii\web\ErrorHandler 錯誤處理器預設使用兩個視圖顯示錯誤:
- @yii/views/errorHandler/error.php: 顯示不包含函數調用棧資訊的錯誤資訊是使用, 當YII_DEBUG 為 false時,所有錯誤都使用該視圖。
- @yii/views/errorHandler/exception.php: 顯示包含函數調用棧資訊的錯誤資訊時使用。
可以配置錯誤處理器的 yii\web\ErrorHandler::errorView 和 yii\web\ErrorHandler::exceptionView 屬性 使用自訂的錯誤顯示視圖。
使用錯誤操作
使用指定的錯誤操作 來自訂錯誤顯示更方便, 為此,首先配置errorHandler組件的 yii\web\ErrorHandler::errorAction 屬性,類似如下:
return [ 'components' => [ 'errorHandler' => [ 'errorAction' => 'site/error', ], ]];
yii\web\ErrorHandler::errorAction 屬性使用路由到一個操作, 上述配置表示不用顯示函數調用棧資訊的錯誤會通過執行site/error操作來顯示。
可以建立site/error 操作如下所示:
namespace app\controllers;use Yii;use yii\web\Controller;class SiteController extends Controller{ public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; }}
上述代碼定義error 操作使用yii\web\ErrorAction 類,該類渲染名為error視圖來顯示錯誤。
除了使用yii\web\ErrorAction, 可定義error 操作使用類似如下的操作方法:
public function actionError(){ $exception = Yii::$app->errorHandler->exception; if ($exception !== null) { return $this->render('error', ['exception' => $exception]); }}
現在應建立一個視圖檔案為views/site/error.php,在該視圖檔案中,如果錯誤操作定義為yii\web\ErrorAction, 可以訪問該操作中定義的如下變數:
- name: 錯誤名稱
- message: 錯誤資訊
- exception: 更多詳細資料的異常對象,如HTTP 狀態代碼,錯誤碼,錯誤調用棧等。
補充: 如果你使用 基礎應用模板 或 進階應用程式模板, 錯誤操作和錯誤視圖已經定義好了。
自訂錯誤格式
錯誤處理器根據響應設定的格式來顯示錯誤, 如果yii\web\Response::format 響應格式為html, 會使用錯誤或異常視圖來顯示錯誤資訊,如上一小節所述。 對於其他的響應格式,錯誤處理器會錯誤資訊作為數組賦值給yii\web\Response::data屬性,然後轉換到對應的格式, 例如,如果響應格式為json,可以看到如下響應資訊:
HTTP/1.1 404 Not FoundDate: Sun, 02 Mar 2014 05:31:43 GMTServer: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8yTransfer-Encoding: chunkedContent-Type: application/json; charset=UTF-8{ "name": "Not Found Exception", "message": "The requested resource was not found.", "code": 0, "status": 404}
可在應用配置中響應response組件的beforeSend事件來自訂錯誤響應格式。
return [ // ... 'components' => [ 'response' => [ 'class' => 'yii\web\Response', 'on beforeSend' => function ($event) { $response = $event->sender; if ($response->data !== null) { $response->data = [ 'success' => $response->isSuccessful, 'data' => $response->data, ]; $response->statusCode = 200; } }, ], ],];
上述代碼會重新格式化錯誤響應,類似如下:
HTTP/1.1 200 OKDate: Sun, 02 Mar 2014 05:31:43 GMTServer: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8yTransfer-Encoding: chunkedContent-Type: application/json; charset=UTF-8{ "success": false, "data": { "name": "Not Found Exception", "message": "The requested resource was not found.", "code": 0, "status": 404 }}
您可能感興趣的文章:
- PHP的Yii架構中行為的定義與Binder 方法講解
- 詳解在PHP的Yii架構中使用行為Behaviors的方法
- 深入講解PHP的Yii架構中的屬性(Property)
- 解讀PHP的Yii架構中請求與響應的處理流程
- PHP的Yii架構中使用資料庫的配置和SQL操作執行個體教程
- 解析PHP的Yii架構中cookie和session功能的相關操作
- 簡要剖析PHP的Yii架構的組件化機制的基本知識
- PHP的Yii架構中YiiBase入口類的擴充寫法樣本
- 詳解PHP的Yii架構的運行機制及其路由功能
- 深入解析PHP的Yii架構中的event事件機制
- 全面解讀PHP的Yii架構中的日誌功能
- PHP的Yii架構中移除組件所綁定的行為的方法
http://www.bkjia.com/PHPjc/1111913.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1111913.htmlTechArticle執行個體講解如何在PHP的Yii架構中進行錯誤和異常處理,執行個體講解yii Yii已經預設已經在CApplication上實現了異常和錯誤的接管,這是通過php的se...