第1章 錯(cuò)誤報(bào)告級別
PHP 程序的錯(cuò)誤一般歸屬于下列三個(gè)領(lǐng)域:
語法錯(cuò)誤:
語法錯(cuò)誤最常見,并且也容易修復(fù)。如:代碼中遺漏一個(gè)分號。這類錯(cuò)誤會阻止腳本的執(zhí)行。
運(yùn)行時(shí)錯(cuò)誤:
這種錯(cuò)誤一般不會阻止PHP腳本的執(zhí)行,但會阻止當(dāng)前要做的事情。輸出一條錯(cuò)誤,但php腳本繼續(xù)執(zhí)行。
邏輯錯(cuò)誤:
這種錯(cuò)誤最麻煩,既不阻止腳本執(zhí)行,也不輸出錯(cuò)誤消息。
案例:
//語法錯(cuò)誤,忘記加分號
echo "123"
//運(yùn)行時(shí)錯(cuò)誤
echo '123';
function laowang(){
echo '456';
}
laoliu();
//邏輯錯(cuò)誤,想要輸出隔壁老王,結(jié)果出現(xiàn)的是帽子,在系統(tǒng)角度看,這并不是錯(cuò)誤。
if(1==1){
echo "帽子";
}else{
echo "隔壁老王";
}
在 PHP 系統(tǒng)中,到底有哪些錯(cuò)誤報(bào)告級別?
在 php.ini 中可以找到錯(cuò)誤級別的說明和設(shè)置。
//表示打開所有錯(cuò)誤提示但屏蔽NOTICE錯(cuò)誤
error_reporting = E_ALL & ~E_NOTICE
//直接關(guān)閉所有錯(cuò)誤提示,開發(fā)階段一般是on,但上線以后一般會選擇off
display_errors = off/on
| 級別常量 | 錯(cuò)誤值 | 錯(cuò)誤報(bào)告描述 |
|---|---|---|
| E_ERROR | 1 | 致命的運(yùn)行時(shí)錯(cuò)誤(阻止腳本執(zhí)行) |
| E_WARNING | 2 | 運(yùn)行時(shí)警告(非致命性錯(cuò)誤) |
| E_PARSE | 4 | 從語法中解析錯(cuò)誤 |
| E_NOTICE | 8 | 運(yùn)行時(shí)注意消息(可能是或可能不是一個(gè)問題) |
| E_CORE_ERROR | 16 | PHP啟動(dòng)時(shí)初始化過程中的致命錯(cuò)誤 |
| E_CORE_WARNING | 32 | PHP啟動(dòng)時(shí)初始化過程中的警告(非致命性錯(cuò)) |
| E_COMPILE_ERROR | 64 | 編譯時(shí)致命性錯(cuò) |
| E_COMPILE_WARNING | 128 | 編譯時(shí)警告(非致命性錯(cuò)) |
| E_USER_ERROR | 256 | 用戶自定義的致命錯(cuò)誤 |
| E_USER_WARNING | 512 | 用戶自定義的警告(非致命性錯(cuò)誤) |
| E_USER_NOTICE | 1024 | 用戶自定義的提醒(經(jīng)常是bug) |
| E_STRICT | 2048 | 編碼標(biāo)準(zhǔn)化警告(建議如何修改以向前兼容) |
| E_ALL | 6143 | 所有的錯(cuò)誤、警告和注意信息 |
//錯(cuò)誤值一般都是系統(tǒng)定義好的常量
echo E_ERROR; //1
//1 2 4 8 ... 6143原理
//利用的二進(jìn)制,采用亮燈的原理,錯(cuò)了就亮。
//000000000001 ---> 就是第一個(gè)錯(cuò)誤
在實(shí)際的開發(fā)中,沒有人關(guān)注什么錯(cuò)誤級別錯(cuò)誤值什么的,報(bào)錯(cuò)了,看一眼大概啥類型的,直接找BUG就行了。
在實(shí)際的開發(fā)中,我們其實(shí)需要做大量的錯(cuò)誤處理,寫功能比較容易,無非就是增刪改查,就像汽車,讓一輛汽車開起來并不難,但如果要做各種安全防護(hù),就要麻煩的多,考慮的因素也非常多,說明書厚的跟字典一樣。
第2章 調(diào)整錯(cuò)誤報(bào)告級別
動(dòng)態(tài)設(shè)置 PHP 錯(cuò)誤信息是否輸出,只在當(dāng)前腳本生效,并不會影響php.ini全局的設(shè)置。
-
display_errors: 是否開啟PHP輸出錯(cuò)誤報(bào)告的功能。
值為:On(默認(rèn)輸出錯(cuò)誤報(bào)告)、 Off(屏蔽所有錯(cuò)誤信息)
在PHP腳本中可調(diào)用ini_set( )函數(shù),動(dòng)態(tài)設(shè)置php.ini配置文件.
如:ini_set("display_errors","On"); //顯示所有錯(cuò)誤信息
//設(shè)置是否輸出錯(cuò)誤信息
ini_set('display_errors',"off");//關(guān)閉
ini_set('display_errors',"on");//開啟
ini_set('display_errors',0);//關(guān)閉
ini_set('display_errors',1);//開啟
//調(diào)用函數(shù)進(jìn)行試驗(yàn)
aa();
error_reporting: 設(shè)置不同的錯(cuò)誤報(bào)告級別。
error_reporting = E_ALL & ~E_NOTICE
-- 可以拋出任何非注意的錯(cuò)誤,默認(rèn)值。
error_reporting = E_ERROR | E_PARSE | E_CORE_ERROR
-- 只考慮致命的運(yùn)行時(shí)錯(cuò)誤、新解析錯(cuò)誤和核心錯(cuò)誤。
error_reporting = E_ALL & ~(E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE)
-- 報(bào)告除用戶導(dǎo)致的錯(cuò)誤之外的所有錯(cuò)誤。
在PHP腳本可以通過error_reporting( )函數(shù)動(dòng)態(tài)設(shè)置錯(cuò)誤報(bào)告級別。如:error_reporting(E_ALL);
//動(dòng)態(tài)設(shè)置錯(cuò)誤等級
error_reporting(E_ALL);
//試驗(yàn),報(bào)所有錯(cuò)誤
echo $a;
//開啟除了notice以外的所有錯(cuò)誤
error_reporting(E_ALL & ~E_NOTICE);
echo $a;
案例:
ini_set('display_errors',1);//開啟
error_reporting(E_ALL);//開啟所有錯(cuò)誤
$sum=0;//此處如果屏蔽掉,初次使用sum時(shí),變量未定義會notice報(bào)錯(cuò)
for($i=0;$i<=10;$i++){
$sum+=$i;
}
echo $sum;
strlen();//字符串長度函數(shù),不給參數(shù),報(bào)warning警告錯(cuò)誤,不會影響程序執(zhí)行
echo "aaaaaaaa";
aa();//致命錯(cuò)誤,調(diào)用一個(gè)不存在的函數(shù)時(shí)程序會終止運(yùn)行。
php.ini 中錯(cuò)誤設(shè)置選項(xiàng)(了解即可,無需深究)。
| 配置指令 | 默認(rèn)值 | 描述 |
|---|---|---|
| display_startup_errors | Off | 是否顯示PHP引擎在初始化時(shí)遇到的錯(cuò)誤 |
| log_errors | Off | 確定日志語句記錄位置 |
| error_log | Null | 設(shè)置錯(cuò)誤可以發(fā)送到syslog中 |
| log_errors_max_len | 1024 | 每個(gè)日志項(xiàng)的最大長度,以字節(jié)為單位,設(shè)置0表示指定最大長度。 |
| ignore_repeated_errors | Off | 是否忽略同一個(gè)文件、同一行發(fā)生的重復(fù)錯(cuò)誤消息 |
| ignore_repeated_source | Off | 忽略不同文件中和同一文件中不同行發(fā)生的重復(fù)錯(cuò)誤。 |
| track_errors | Off | 啟動(dòng)該指令會使PHP在$php_errormsg中存儲最近發(fā)生的錯(cuò)誤信息。 |
第3章 PHP 日志的記錄方式
1)采用文件記錄 (推薦使用)。
2) 錯(cuò)誤日志記錄到操作系統(tǒng)日志中。
思考:為什么要做日志記錄?
1.方便自己開發(fā)的時(shí)候查詢,框架一般都自帶日志功能,只需要開啟就OK。
2.可以借助運(yùn)行日志開發(fā)相應(yīng)的后臺日志功能,給管理員查詢,方便管理。
3.1 采用文件記錄
先配置 php.ini 文件
error_reporting = E_ALL //將向PHP發(fā)送每個(gè)錯(cuò)誤
display_errors=Off //不顯示錯(cuò)誤報(bào)告
* log_errors=On //決定日志語句記錄的位置
log_errors_max_len=1024 //每個(gè)日志項(xiàng)的最大長度
* error_log=G:/myerror.log //指定錯(cuò)誤寫進(jìn)的文件
試驗(yàn):
a();//注意觀察日志文件
conunt();//注意觀察日志文件
以上記錄的是系統(tǒng)報(bào)錯(cuò)的日志。
思考:我能不能做一個(gè)用戶操作的人為的日志?
使用函數(shù):在 PHP 文件中使用 error_log() 來記錄日志,就可以將信息寫入到 myerror.log 文件中。
error_log("用戶xxx想刪除ID為69的用戶名,已經(jīng)記錄到日志,請注意這個(gè)小子");
參數(shù)參考手冊。
rigger_error() 函數(shù)記錄日志
上一節(jié)中,我們使用error_log()報(bào)一個(gè)自定義的錯(cuò)誤信息,讓系統(tǒng)記錄,只記錄信息。
而使用 trigger_error() 比 error_log 更加靈活一些,可指定等級和文件位置。
//可利用系統(tǒng)提供的錯(cuò)誤等級給日志記錄自己定義好的錯(cuò)誤信息,默認(rèn)為notic級別
trigger_error("用戶xxx想刪除ID為69的用戶名,已經(jīng)記錄到日志,請注意這個(gè)小子",E_USER_ERROR);
3.2 錯(cuò)誤日志記錄到操作系統(tǒng)日志中
先配置 php.ini 文件
error_reporting = E_ALL //將向PHP發(fā)送每個(gè)錯(cuò)誤
* display_errors=Off //不顯示錯(cuò)誤報(bào)告
* log_errors=On //決定日志語句記錄的位置
log_errors_max_len=1024 //每個(gè)日志項(xiàng)的最大長度
* error_log=syslog //指定錯(cuò)誤寫進(jìn)的文件
使用四個(gè)函數(shù)來記錄日志:
//define_syslog_variables(); 為系統(tǒng)日志初始化配置
//openlog(); 打開一個(gè)日志鏈接
//syslog(); 發(fā)送一條日志記錄
//closelog(); 關(guān)閉日志鏈接
試驗(yàn):
aa();//不再顯示日志,而是記錄到系統(tǒng)日志中去了。
目前的開發(fā)已經(jīng)淘汰這種方式,4個(gè)函數(shù)必須同時(shí)使用,課后可自行試驗(yàn),代碼如下:
define_syslog_variables();
openlog("PHP5", LOG_PID , LOG_USER);
syslog(LOG_WARNING, "警告報(bào)告向syslog中發(fā)送的演示,警告時(shí)間: ".date("Y/m/d H:i:s"));
closelog();
如何查看 Window 系統(tǒng)日志。
計(jì)算機(jī)右鍵 ---> 管理(G) ---> 系統(tǒng)工具 ---> 事件查看器 ---> Windows 日志 ---> 應(yīng)用程序
第4章 自定義錯(cuò)誤處理
自定義錯(cuò)誤報(bào)告的處理方式,可以完全繞過標(biāo)準(zhǔn)的PHP錯(cuò)誤處理函數(shù),這樣就可以按自己定義的格式打印錯(cuò)誤報(bào)告,或改變錯(cuò)誤報(bào)告打印的位置。
說白了就是不使用系統(tǒng)的錯(cuò)誤提示,改為自己的。
set_error_handler() -- 設(shè)置用戶自定義錯(cuò)誤處理。
參數(shù):mixed set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] )
回調(diào)函數(shù):回來調(diào)取函數(shù)。
所謂的回調(diào)函數(shù):
function demo(){
return "我才不要呢";
}
function demo2(){
return "我也不要";
}
function result($suan){
return $suan();
}
//將函數(shù)名demo1 函數(shù)名demo2 作為字符串參數(shù)傳遞給result函數(shù),那么可以自動(dòng)調(diào)用上面的函數(shù),我們就說demo1,demo2是result的回調(diào)函數(shù)
echo result('demo2');
案例:
//回調(diào)函數(shù)也需要參數(shù)接收,參考手冊
/*
errno
第一個(gè)參數(shù) errno,包含了錯(cuò)誤的級別,是一個(gè) integer。
errstr
第二個(gè)參數(shù) errstr,包含了錯(cuò)誤的信息,是一個(gè) string。
errfile
第三個(gè)參數(shù)是可選的,errfile, 包含了發(fā)生錯(cuò)誤的文件名,是一個(gè) string。
errline
第四個(gè)參數(shù)是一個(gè)可選項(xiàng), errline, 包含了錯(cuò)誤發(fā)生的行號,是一個(gè) integer。
*/
function callbackset($errno,$errstr,$errfile,$errline){
echo "自定義錯(cuò)誤處理:錯(cuò)誤級別:{$errno},錯(cuò)誤信息是:{$errstr}.所在文件:{$errfile}的第{$errline}行";
}
set_error_handler("callbackset");//此處設(shè)置為報(bào)錯(cuò)的返回信息交給callbackset自行處理
echo $aa;
特別注意:E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING是不會有效果的,通常會用原始的方式顯示。