本文介紹php開源庫BooBoo简僧,是一個處理php異常和錯誤的開源庫,通過簡單的分析代碼,我們知道了實(shí)際項(xiàng)目中怎么正確的設(shè)置錯誤和異常料饥。
這是php異常系列的第二篇,第一篇地址是:
基本概念
php中的異常和錯誤是不一樣的朱监,錯誤英文單詞是error岸啡,異常英文單詞是exception。異常一般指出現(xiàn)正常邏輯之外的情況赫编,而錯誤是指運(yùn)行時發(fā)生了不可恢復(fù)的故障巡蘸,比如使用了未定義的變量奋隶,或者語法錯誤等。異常我們通過throw
拋出悦荒,catch
進(jìn)行捕獲唯欣,而錯誤一般發(fā)生程序就會終止,我們可以通過trigger_error
觸發(fā)用戶級錯誤逾冬,然后通過set_error_handler
設(shè)置處理函數(shù)黍聂,下面看段代碼:
set_error_handler('errorHandler');
trigger_error("這里描述錯誤",E_USER_ERROR);
//E_USER_ERROR:該error 所特定的錯誤類型躺苦,默認(rèn)是E_USER_NOTICE
function errorHandler($errno,$errstr){
//用戶的函數(shù)需要接受兩個參數(shù):錯誤碼和描述錯誤的 string
if($errno==E_USER_ERROR){
echo "錯誤為:",$errstr.'<br>';
}
}
運(yùn)行后就會通過我們設(shè)定的errorHandler
輸出錯誤身腻。
如果我們沒有設(shè)定errorHandler,而且我們是在控制臺中運(yùn)行的腳本匹厘,那就會出現(xiàn)錯誤信息嘀趟,
PHP Fatal error: 這里描述錯誤 in /Users/zhuanxu/workspace/php-exceptions/error.php on line 4
那我們怎么能夠在生產(chǎn)環(huán)境中去除這些信息呢?
在php.ini中有兩個參數(shù)與錯誤有關(guān)愈诚,一個是display_errors她按,另一個是error_reporting,其中display_errors控制著是否將錯誤信息輸出到控制臺炕柔,而error_reporting則控制著錯誤報(bào)告級別酌泰。
講完這些,我們下面將開始分析BooBoo匕累,來看看實(shí)際項(xiàng)目中怎么處理錯誤和異常陵刹。
BooBoo介紹
此處我們通過庫BooBoo來進(jìn)行學(xué)習(xí)。
BooBoo的設(shè)計(jì)原則是:如果Errors是fatal的欢嘿,那就按fatal處理衰琐,如果Errors不是Fatal的,則讓程序繼續(xù)執(zhí)行炼蹦。
在錯誤的處理上羡宙,我們希望能夠在實(shí)際生產(chǎn)中處理錯誤,但是只在開發(fā)環(huán)境中才展示出這些錯誤信息掐隐,因此BooBoo在設(shè)計(jì)上有兩個重要的概念:Handler狗热,F(xiàn)ormatter。
- Handler做的事情就是針對錯誤執(zhí)行一個操作虑省,可能是記錄日志斗搞,可能是發(fā)送錯誤給報(bào)警器。
- Formatter則是將錯誤變?yōu)榭砷喿x的錯誤信息慷妙。
另外當(dāng)設(shè)置display_errors關(guān)閉的時候僻焚,不會執(zhí)行Formatter操作,當(dāng)然BooBoo也支持你自己針對錯誤自己制定Formatter膝擂。
代碼結(jié)構(gòu):
├── Exception
│ └── NoFormattersRegisteredException.php
├── Formatter
│ ├── AbstractFormatter.php
│ ├── CommandLineFormatter.php
│ ├── FormatterInterface.php
│ ├── HtmlFormatter.php
│ ├── HtmlTableFormatter.php
│ ├── JsonFormatter.php
│ └── NullFormatter.php
├── Handler
│ ├── HandlerInterface.php
│ ├── LogHandler.php
│ └── RavenHandler.php
├── Runner.php
└── Util
├── Frame.php
├── FrameCollection.php
└── Inspector.php
頂層是Runner.php虑啤,下面是重要的兩個目錄:Formatter和Handler隙弛,還有輔助函數(shù)Util,以及異常Exception狞山。
我們先看使用方式
安裝
$ composer require league/booboo
新建booboo.php
use League\BooBoo\Formatter\CommandLineFormatter;
use League\BooBoo\Runner;
require_once __DIR__ . "/vendor/autoload.php";
$runner = new Runner();
$runner->pushFormatter(new CommandLineFormatter());
$runner->register(); // Registers the handlers
echo $cc;
執(zhí)行后輸出:
+--------+
| NOTICE |
+--------+
Undefined variable: cc in /Users/zhuanxu/workspace/php-exceptions/booboo.php on line 12
有了使用的感性認(rèn)識后全闷,我們看看究竟發(fā)生了什么。
在League\BooBoo\Runner
的構(gòu)造函數(shù)中:
public function __construct(array $formatters = [], array $handlers = []);
可以設(shè)置formatters和handlers萍启,然后在register函數(shù)中总珠,
//==> 關(guān)閉錯誤展示,設(shè)置3個處理函數(shù)
// We want the formaters we register to handle the errors.
ini_set('display_errors', false);
set_error_handler(array($this, self::ERROR_HANDLER));
set_exception_handler(array($this, self::EXCEPTION_HANDLER));
register_shutdown_function(array($this, self::SHUTDOWN_HANDLER));
通過3個注冊函數(shù)注冊了處理的函數(shù)勘纯。當(dāng)異常發(fā)生的時候局服,調(diào)用exceptionHandler
函數(shù)
里面會挨個調(diào)用用戶注冊的handlers,如果用戶沒有關(guān)閉錯誤顯示驳遵,會通過formatters處理后直接打印出來淫奔,但是如果關(guān)閉了錯誤顯示,則會返回給瀏覽器堤结。
此處看下register_shutdown_function函數(shù)唆迁,其注冊的函數(shù)調(diào)用條件是:
1、當(dāng)頁面被用戶強(qiáng)制停止時
2竞穷、當(dāng)程序代碼運(yùn)行超時時
3唐责、當(dāng)PHP代碼執(zhí)行完成時,代碼執(zhí)行存在異常和錯誤瘾带、警告
在函數(shù)shutdownHandler中:我們關(guān)閉了拋出異常鼠哥,然后判斷是否有錯誤發(fā)生,有則進(jìn)行錯誤處理月弛。
public function shutdownHandler()
{
// We can't throw exceptions in the shutdown handler.
$this->treatErrorsAsExceptions(false);
$error = error_get_last();
if ($error && $error['type'] & $this->fatalErrors) {
$this->errorHandler(
$error['type'],
$error['message'],
$error['file'],
$error['line']
);
}
}
最后我們看下錯誤處理函數(shù)肴盏,在里面我們會判斷錯誤是否是致命錯誤,如果是則進(jìn)行處理帽衙,否則按照異常處理菜皂。
BooBoo庫的介紹就到這了,通過BooBoo我們能很方便的對異常和錯誤進(jìn)行統(tǒng)一處理厉萝,非常方便我們平常的開發(fā)恍飘,下一篇我們將再看看Whoops庫,也是一個錯誤處理的函數(shù)谴垫,再平時開發(fā)中用到的很多章母。
這是 php異常系列 的第二篇,你的鼓勵是我繼續(xù)寫下去的動力翩剪,期待我們共同進(jìn)步乳怎。