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