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