Yii2 之錯誤處理深入分析
▪ 前言
在 Yii2 使用中,我們發現一但程式出現錯誤,Yii2 就能自動顯示其專用的錯誤提示介面,和我們寫原生態時出現的錯誤提示介面完全不一樣。它究竟是怎麼做到的呢:是在哪裡設定監聽的?亦或在哪裡用的try catch?”。
其實 PHP 有自己專用的錯誤處理 API, 當程式出現問題時,可以自動呼叫指定函式。而 Yii2 正是利用這一點,在其啟動的時候,使用 PHP 內建的 set_error_handler
將自己的錯誤處理註冊進步並關閉 PHP 自身的錯誤顯示。
▪ Yii2 錯誤自定義處理
在 官方教程 中,它告訴我們要開啟自定義的錯誤,需要進行如下配置元件:
return [
// ...
'components' => [
// ...
'errorHandler' => [
'errorAction' => 'site/error',
],
]
// ...
];
'errorAction' => 'site/error'
表示一但發生錯誤,那麼 Yii2 將呼叫SiteController
控制器的errorAction
方法,該方法是你自己自定義顯示錯誤的入口。
實際開發中很多新手發現雖然填寫了這個配置,但是發現 Yii2 並沒有如我們所想的進入到 SiteController
控制器的 errorAction
方法,究竟是什麼原因?看下面我們一步一步來解釋。
▪ Yii2 錯誤序號產生器制
X. 預定義開啟錯誤處理常量
下面的變數將控制是否開啟錯誤處理,預設為開啟,你可以通過設定該變數值關閉錯誤日誌
# \yii\BaseYii.php
/**
* This constant defines whether error handling should be enabled. Defaults to true.
*/
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER', true);
X. 預定義預設元件 errorHandler
下面的函式主要是設定錯誤處理的預設類,如果你的配置檔案中沒有設定 errorHandler
的 class
,那麼將直接使用 'yii\web\ErrorHandler'
類物件進行處理:
# yii2\web\Application.php
/**
* @inheritdoc
*/
public function coreComponents()
{
return array_merge(parent::coreComponents(), [
'request' => ['class' => 'yii\web\Request'],
'response' => ['class' => 'yii\web\Response'],
'session' => ['class' => 'yii\web\Session'],
'user' => ['class' => 'yii\web\User'],
'errorHandler' => ['class' => 'yii\web\ErrorHandler'],
]);
}
X. 執行時初始化註冊錯誤處理機制流程
應用入口檔案 index.php
初始化時將呼叫基類的 yii\base\Application.php
建構函式,其中包含了開始註冊錯誤處理機制:
# index.php
// ...
(new yii\web\Application($config))->run();
# yii\base\Application.php
public function __construct($config = [])
{
Yii::$app = $this;
$this->setInstance($this);
$this->state = self::STATE_BEGIN;
$this->preInit($config);
// 開始註冊錯誤處理機制
$this->registerErrorHandler($config);
Component::__construct($config);
}
// ...
/**
* 註冊錯誤處理元件
* @param array $config application config
*/
protected function registerErrorHandler(&$config)
{
if (YII_ENABLE_ERROR_HANDLER) {
// 獲取錯誤處理元件資訊
if (!isset($config['components']['errorHandler']['class'])) {
echo "Error: no errorHandler component is configured.\n";
exit(1);
}
$this->set('errorHandler', $config['components']['errorHandler']);
unset($config['components']['errorHandler']);
// 獲取錯誤處理物件並註冊錯誤處理鉤子
$this->getErrorHandler()->register();
}
}
上述的 $this->getErrorHandler()->register();
將呼叫如下程式碼:
# yii\base\ErrorHandler
/**
* Register this error handler
*/
public function register()
{
// 關閉 PHP 原始錯誤提示
ini_set('display_errors', false);
// 程式碼的 $this 表示 yii\base\ErrorHandler 的類物件
// 實際情況 Yii2 是構建了 yii\web\ErrorHandler 的類物件,其繼承自 yii\base\ErrorHandler 類
// 註冊異常的處理鉤子
set_exception_handler([$this, 'handleException']);
// 註冊錯誤的處理鉤子
if (defined('HHVM_VERSION')) {
set_error_handler([$this, 'handleHhvmError']);
} else {
set_error_handler([$this, 'handleError']);
}
if ($this->memoryReserveSize > 0) {
$this->_memoryReserve = str_repeat('x', $this->memoryReserveSize);
}
register_shutdown_function([$this, 'handleFatalError']);
}
由於元件裡預設
errorHandler
的處理類是yii\web\ErrorHandler
,所以上述程式碼set_exception_handler([$this, 'handleException']);
表示呼叫yii\web\ErrorHandler
類物件的handleException
方法,同理set_error_handler([$this, 'handleError']);
將類物件呼叫handleError
來顯示錯誤
通過上面的方法,我們能看到,Yii2 通過 PHP 異常處理函式 set_exception_handler
設定處理異常的方法,通過錯誤處理函式 set_error_handler
設定了處理錯誤的方法。當有程式碼中有異常或者錯誤設定的時候,如果上層沒有進一步的異常處理機制,就會被整個全域性函式捕捉,並加以處理。
▪ Yii2 錯誤核心處理方法
在 Yii2 錯誤自定義處理 中我們瞭解了 Yii2 錯誤註冊的原理並知道錯誤的發生後,Yii2 將呼叫 yii\web\ErrorHandler
類物件的 handleException
和 handleError
方法。
其實 yii\web\ErrorHandler
類中並沒有 handleException
和 handleError
方法,但是在其基類 yii\base\ErrorHandler
有,這兩個函式最終都將呼叫 yii\web\ErrorHandler
的 renderException
方法,程式碼如下:
# yii\web\ErrorHandler
/**
* Renders the exception.
* @param \Exception $exception the exception to be rendered.
*/
protected function renderException($exception)
{
// ...
// 注意:控制錯誤是否能自定義的關鍵
// !YII_DEBUG 表示瞭如果你現在是在 Debug 模式下,那麼不能自定義錯誤
// 即使你配置了元件的 'errorHandler' => ['errorAction' => 'site/error'] 引數
$useErrorView = $response->format === Response::FORMAT_HTML && (!YII_DEBUG || $exception instanceof UserException);
// 傳遞到自定義錯誤處理方法
if ($useErrorView && $this->errorAction !== null) {
$result = Yii::$app->runAction($this->errorAction);
if ($result instanceof Response) {
$response = $result;
} else {
$response->data = $result;
}
}
// ...
}
在最終的錯誤顯示方法 renderException
我們可以看出:自定義的錯誤需特定的情況下才能生效
▪ Yii2 自定義錯誤使用
相關文章
- Golang通脈之錯誤處理Golang
- 錯誤處理
- 開心檔之Go 錯誤處理Go
- Python錯誤處理Python
- PHP 錯誤處理PHP
- php錯誤處理PHP
- Go 錯誤處理Go
- 錯誤處理:如何通過 error、deferred、panic 等處理錯誤?Error
- openGauss 處理錯誤表
- go的錯誤處理Go
- axios 的錯誤處理iOS
- Python之錯誤異常和檔案處理Python
- Python錯誤處理和異常處理(二)Python
- Oracle異常錯誤處理Oracle
- 淺談前端錯誤處理前端
- ORACLE 異常錯誤處理Oracle
- PHP 核心特性 - 錯誤處理PHP
- 15-錯誤處理(Error)Error
- Go語言之錯誤處理Go
- grpc中的錯誤處理RPC
- laravel9 錯誤處理Laravel
- 學習Rust 錯誤處理Rust
- rust學習十、異常處理(錯誤處理)Rust
- node端統一錯誤處理
- node錯誤處理與日誌
- [轉] Scala Try 與錯誤處理
- js錯誤處理權威指北JS
- [譯] 使用 Catcher 處理 Flutter 錯誤Flutter
- 如何處理錯誤訊息PleaseinstalltheLinuxkernelheaderfilesLinuxHeader
- 錯誤碼全域性處理(二)
- 錯誤碼全域性處理(一)
- PHP安裝後錯誤處理PHP
- 常用模組 PHP 錯誤處理PHP
- Restful API 中的錯誤處理RESTAPI
- 請教 Element 的錯誤處理
- 異常錯誤資訊處理
- 程式錯誤型別及其處理型別
- oracle ora-00054錯誤處理Oracle