PHP開發(fā)基礎(chǔ)教學(xué)之Error
一、問題引入
在之前我們寫程式碼的時候常常會看到:函數(shù)名寫錯了,忘加分號了,函數(shù)被重新定義了都會報各種不同樣的錯。
在開發(fā)中,顯示錯誤對我們的開發(fā)非常有利。因為,顯示錯誤後能幫我們快速定位錯誤、解決問題。
而在生產(chǎn)環(huán)境(即公網(wǎng))給其他人訪問的的網(wǎng)站、微網(wǎng)站、手機(jī)網(wǎng)站、手機(jī)介面... ...等等。
如果錯誤顯示出來了,就容易暴露:
伺服器的檔案路徑和檔案儲存規(guī)範(fàn)
有些人喜歡用個人名稱命名,透過社會工程學(xué)可以反向推理出密碼
有時還會暴露mysql資料庫伺服器的位址
... ... 等等
上面這些資訊特別容易被網(wǎng)路上別有用心的一些人給利用。
例如下面這段程式碼,我們不加分號就全面暴露了我們的伺服器端檔案存放路徑、框架資訊等。如下:
<?php $fp = fopen('abc.txt','a+') fwrite($fp,'abc'); fclose($fp); ?>
報錯了:
?
#錯誤提示中文翻譯過來為:
解析錯誤:語法錯誤。意外發(fā)生在/home/vagrant/Code/Laravel/public/index.php 檔案的第5行fwrite附近。
在本章中,我們來嘗試解決這個問題
#二、禁止顯示錯誤
在php .ini設(shè)定檔中。我們可以控制php的錯誤顯示狀態(tài)。
php.ini中有一個專門的設(shè)定項:
display_errors
這個選項設(shè)定是否將錯誤訊息輸出到網(wǎng)頁,或是對用戶隱藏而不顯示。
這個值的狀態(tài)為on 或 off,也可以設(shè)為1 或0。
display_error的值設(shè)為0或off則不在頁面中顯示錯誤,如果設(shè)為1或on則顯示錯誤訊息。
問題:如果沒有修改伺服器php.ini的狀態(tài)權(quán)限怎麼辦?
可以使用ini_set。
<?php ini_set('display_errors' , 0 ); ?>
上面的程式碼也相當(dāng)於修改了php.ini中display_errors的值。不過,僅僅在目前php程式碼中生效。
問題:想取得php.ini的設(shè)定項目狀態(tài)怎麼辦?
可以使用ini_get(參數(shù)項) 來得到參數(shù)的值。
實例:
<?php echo '服務(wù)器中display_errors的狀態(tài)為' . ini_get('display_errors'); ?>
附註:修改完php.ini文件,需要重新啟動伺服器。
三、錯誤回報等級
#1.錯誤類型
##php大家最常見的錯誤顯示:
- error最嚴(yán)重,必須要解決。不然程式無法繼續(xù)向下執(zhí)行
?warning也很重要。通也必須解決。如果明確的,故意的可以不用處理。
?notice 你可以不用管。但是在有些公司,專案標(biāo)準(zhǔn)特別高。在高標(biāo)準(zhǔn)要求的項目中也必須解決。因為,notice會影響PHP的執(zhí)行效率。通常發(fā)生在函數(shù)未定義等。
parse錯誤,是指語法錯誤寫錯了,必須解決
代表全部類型的所有錯誤
其它根據(jù)上面擴(kuò)展出來的另外一些需要了解的錯誤項:
在學(xué)習(xí)過程中,上面的類型了解即可。因為基本上不會遇到,遇到了大家去查一下或查一下手冊就清楚了。
2.error_reporting 報告錯誤類型
error_reporting 是指錯誤報告。在php.ini中也有這樣一個參數(shù)。這個參數(shù)。決定了PHP引擎記錄、報告、顯示哪些錯誤類型。
1)、 在php.ini中error_reporting參數(shù)。
如若error_reporting參數(shù)設(shè)定為0。整個PHP引擎發(fā)出錯誤均不會顯示、輸出、記錄。在下一章將要講到的日誌記錄中,也不會記錄。
如果我們想顯示所有錯誤可以寫上:
error_reporting = E_ALL
想要顯示所有錯誤但排除提示,可以將這個參數(shù)寫成:
error_reporting = E_ALL & ~ E_NOTICE
顯示所有錯誤,但排除提示、相容性和未來相容性??蓪憺椋?/p>
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
2)、在某些情況下我們無權(quán)限操作php.ini文件,又想要控制error_reporting怎麼辦呢?
在執(zhí)行的xxxx.php檔案中開始處,我們可以使用error_reporting()函數(shù)達(dá)到目標(biāo)。
示範(fàn)程式碼如下:
<?php //關(guān)閉了所有的錯誤顯示 error_reporting(0); //顯示所有錯誤 //error_reporting(E_ALL); //顯示所有錯誤,但不顯示提示 //error_reporting(E_ALL & ~ E_NOTICE); ?>
上面的程式碼你可以試試,故意寫錯程式碼看看。在目前文件中也會不會顯示指定的錯誤。
[擴(kuò)充、了解知識點]:?@ 符是我們之前學(xué)過的單行不顯示錯誤,請不用或少用@符。
我們拿讀取一個不存在的文件,這樣的php程式碼來示範(fàn)實作過程:
<?php //讀取一個不存在的adsaf.txt文件,用@符抑制錯誤 @$fp = fopen('adsaf.txt','r'); ?> @符效率較低,它在php內(nèi)核中的實現(xiàn)過程是: <?php //關(guān)閉錯誤 error_reporting(0); //讀取一個不存在的文件,顯示錯誤 //顯示錯誤 error_reporting(E_ALL & ~ E_NOTICE); ?>
四、錯誤記錄日誌
在某些公司裡面,有專門的日誌收集系統(tǒng)。日誌收集系統(tǒng)會在背後默默的幫你收集錯誤、警告、提示。
也有些公司沒有專門的日誌收集系統(tǒng),透過檔案來伺服器當(dāng)中的運行日誌。
其中:PHP的錯誤,警告這些是必須要收集的。
那麼問題來了-不讓使用者看到,設(shè)定好錯誤報告等級好,如何將錯誤收集到日誌系統(tǒng)呢?
這裡有需要使用到php.ini的相關(guān)設(shè)定項。這兩個配置項為:
說明:
#?在表格中的log_errors和log_errors_max_len非常好理解。
?而error_log 指定將錯誤存在什麼路徑上。配置項目中的syslog可能有點不太好理解。 syslog是指系統(tǒng)來記錄。 windows系統(tǒng)在電腦的日誌收集器裡面。 linux預(yù)設(shè)在:/etc/syslog.conf
[擴(kuò)充]?了解知識點。若Linux系統(tǒng)啟動或修改了日誌收集??赡軆Υ嬖诘谌綄S玫娜照I收集伺服器中。
此外,PHP還為我們專門準(zhǔn)備了一個自訂的錯誤日誌函數(shù):
bool error_log ( string $錯誤訊息[, int $錯誤訊息類型= 0 [, string $存儲目標(biāo)]] )
這個函數(shù)可以把錯誤訊息傳送到web伺服器的錯誤日誌,或是到一個檔案裡。
常用的錯誤訊息類型:
範(fàn)例:
<?php //無法連接到數(shù)據(jù)庫服務(wù)器,直接記錄到php.ini 中的error_log指定位置 error_log("無法連接到數(shù)據(jù)庫服務(wù)器服務(wù)器"); //可以發(fā)送郵件,但是php.ini必須配置過郵件系統(tǒng) error_log('可以用郵件報告錯誤,讓運維人員半夜起床干活',1 ,'liwenkai@phpxy.com'); //記錄在指定的位置 error_log("我是一個錯誤喲", 3, "d:/test/my-errors.log"); ?>
附註:
error_log 中發(fā)送郵件可能對初學(xué)者不熟,您可以不用掌握些塊知識。
#五、自訂錯誤處理函數(shù)
#這一塊知識起點有些高。大多數(shù)人沒有軟體工程、自訂錯誤處理的經(jīng)驗,很難想像使用的場景。若你想跳過此區(qū)塊的學(xué)習(xí),完全可以,並且我們支援。
此區(qū)塊知識點對於實際應(yīng)用程式中應(yīng)用場景不多。如果,有計畫開始要自己寫框架時、或您做完了本書的第一個專案。
使用者自訂錯誤常用到的兩個函數(shù):
set_error_handler ( callable $回呼的錯誤處理函數(shù))
設(shè)定一個使用者定義的錯誤處理函數(shù)
trigger_error ( string $error_msg)
產(chǎn)生一個使用者層級的error/warning/notice 資訊
<?php //定義一個自定義的錯誤處理函數(shù) function customError($errno, $errstr, $errfile, $errline) { //輸出錯誤消息 echo "<b>Custom error:</b> [$errno] $errstr<br />"; //輸出錯誤文件和錯誤行 echo "Error on line $errline in $errfile<br />"; echo "Ending Script"; //中止程序運行 exit; } //使用set_error_handler 綁定用戶自定義函數(shù) set_error_handler("customError"); $test=2; //觸發(fā)自定義錯誤 if ($test > 1) { trigger_error("A custom error has been triggered"); } ?>