在PHP 5之前,PHP對於錯誤處理(Error)採用以下的方法:
<?php
//自訂錯誤處理函數,PHP預設錯誤常數,錯誤訊息,錯誤發生的檔案,錯誤發生的行號
function custom_error($errno, $errstr, $errfile, $errline){
//如果回傳true,不要讓PHP來正常處理錯誤(不拋出)
return true;
//如果回傳false,則代表讓PHP來正常處理錯誤(拋出)
//return false;
}
//設定錯誤需要報告的等級
error_reporting(E_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING|E_NOTICE|E_USER_NOTICE);
//如果不設定就讓PHP來正常處理錯誤(拋出)
set_error_handler("custom_error");
//因為customer_error傳回true則
echo $ary['err'].'<br />';
echo 'after error'.'<br />';
?>
error_reporting函數所代表的,是那些錯誤等級需要PHP將其處理與呈現,如果不加上這一句,代表所有錯誤等級皆會處理,也就是錯誤等級E_ALL,錯誤等級列表如下:http://tw2.php.net/manual/en/errorfunc.constants.php
如果要針對錯誤進行相關處理,可以藉由set_error_handler來指定錯誤處理函數,而錯誤處理函數的帶入參數為:自訂錯誤處理函數、PHP預設錯誤常數、錯誤訊息、錯誤發生的檔案、錯誤發生的行號。
上述的範例中,「$ary['err']」這一行一定會錯,所以如果錯誤處理函數回傳為true,代表不要讓PHP來正常處理錯誤(不拋出),如果回傳false,則代表讓PHP來正常處理錯誤(拋出),當然也可以在錯誤處理函數裡針對不同等級的錯誤來進行相關處理,如下範例:
<?php
function custom_error($errno, $errstr, $errfile, $errline){
//
$stop_flag = false;
//可以依照錯誤的等級個別指定處理方式
switch ($errno){
case E_USER_ERROR:
echo 'E_USER_ERROR<br/>';
$stop_flag = true;
break;
case E_USER_WARNING:
echo 'E_USER_WARNING<br/>';
$stop_flag = true;
break;
case E_USER_NOTICE:
echo 'E_USER_NOTICE<br/>';
$stop_flag = true;
break;
case E_ERROR:
echo 'E_ERROR<br/>';
$stop_flag = true;
break;
case E_WARNING:
echo 'E_WARNING<br/>';
$stop_flag = true;
break;
case E_NOTICE:
echo 'E_NOTICE<br/>';
$stop_flag = true;
break;
default:
echo 'other error<br/>';
$stop_flag = true;
}
return $stop_flag;
}
//
error_reporting(E_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING|E_NOTICE|E_USER_NOTICE);
set_error_handler("custom_error");
//
echo $ary['err'].'<br />';
echo 'after error'.'<br />';
?>
而PHP 5之後,開始加入Exception的例外處理模式,也就是其他語言中所熟知的Try…Catch..語法,但是在目前的PHP 5裡尚未加入Finally的語法,如果要在PHP裡讓Exception可以抓到錯誤,則必須拋出Exception,如下面範例中的「throw new Exception("custom exception!");」,但是針對之前我們所介紹的錯誤,卻是無法進行抓取:
<?php
//try...catch 用法
try{
throw new Exception("custom exception!");
} catch (Exception $e) {
echo "例外的訊息字串 : " . $e->getMessage()."<br />";
echo "產生例外的檔案 : " . $e->getFile()."<br />";
echo "產生例外的行號 : " . $e->getLine()."<br />";
echo "產生例外的程式碼 : " . $e->getCode()."<br />";
echo "例外的堆疊追蹤陣列 : ";
print_r($e->getTrace());
echo "<br />";
echo "例外的堆疊追蹤字串 : " . $e->getTraceAsString()."<br />";
echo "例外的表示字串 : " . $e->__toString()."<br />";
}
echo 'after exception...'.'<br/>';
//但是error無法使用
try{
echo $ary['err'];
} catch (Exception $e) {
echo $e->getMessage()."<br />";
}
?>
所以我們可以在錯誤處理函數裡拋出ErrorException,這樣不管是怎樣的錯誤等級,都可以使用Exception來進行處理,當然也可以在錯誤處理函數裡區分錯誤等級,不一定所有錯誤等級都要拋出ErrorException。
<?php
function custom_error($errno, $errstr, $errfile, $errline){
//發生Error就直接拋出Exception,以便後續可以使用try~catch處理
//錯誤訊息,內部代碼,PHP預設錯誤常數,錯誤發生的檔案,錯誤發生的行號
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
//
error_reporting(E_ERROR|E_USER_ERROR|E_WARNING|E_USER_WARNING|E_NOTICE|E_USER_NOTICE);
set_error_handler("custom_error");
//
try{
echo $ary['err'];
} catch (Exception $e) {
echo $e->getMessage().'<br />';
}
echo 'after error exception...'."<br />";
?>
當然可以使用PHP 5之後的物件導向的類別,將其包裝成可重覆使用的物件,以減少程式碼的產生,也可以在該類別中加上記錄的函數,將其記錄到所指定的文件裡,以下範例是每天會產生出一個檔案來記錄
<?php
class error_handler{
public function error_handler(){
}
public static function custom_error($errno, $errstr, $errfile, $errline){
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
public static function record(Exception $e){
//先指定時區
date_default_timezone_set('Asia/Taipei');
//格式化錯誤訊息
$err_str = sprintf("錯誤發生日期: %s[錯誤訊息: %s]\r\n 錯誤檔案: %s\r\n 錯誤行號 : %s\r\n 錯誤堆疊追蹤字串: %s\r\n-------------\r\n",
date("Y-m-d H:m:s"), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString());
//在檔案內記錄
error_log($err_str, 3, "C:\\error_log\\".date("Ymd").".log");
}
}
?>
<?php require_once 'error_handler.php';?>
<?php
$error_handler = set_error_handler("error_handler::custom_error");
try{
echo $ary['err'];
} catch (Exception $e) {
error_handler::record($e);
echo '系統發生錯誤!';
}
?>
轉貼請註明出處,最好直接使用聯結轉貼!Thanks~
作者: Samuel - 林靖傑
日期:2012/10/12
沒有留言:
張貼留言