PHP 程序的錯誤通常歸屬於下列三個領域:php
語法錯誤:安全
語法錯誤最多見,而且也容易修復。如:代碼中遺漏一個分號。這類錯誤會阻止腳本的執行。 服務器
運行時錯誤:框架
這種錯誤通常不會阻止PHP腳本的執行,但會阻止當前要作的事情。輸出一條錯誤,但php腳本繼續執行。函數
邏輯錯誤:工具
這種錯誤最麻煩,既不阻止腳本執行,也不輸出錯誤消息。編碼
圖解 Apache Web 服務器與 PHP 引擎的關係。操作系統
案例:.net
//語法錯誤,忘記加分號 echo "123" //運行時錯誤 echo '123'; function laowang(){ echo '456'; } laoliu(); //邏輯錯誤,想要輸出隔壁老王,結果出現的是帽子,在系統角度看,這並非錯誤。 if(1==1){ echo "帽子"; }else{ echo "隔壁老王"; }
在 PHP 系統中,到底有哪些錯誤報告級別?日誌
在 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全局的設置。
值爲: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 = 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是不會有效果的,一般會用原始的方式顯示。