php異常處理
什么是異常?
- PHP 5 提供了一種新的面向對象的錯誤處理方法。異常處理用於在指定的錯誤(異常)情況發生時改變腳本的正常流程。這種情況稱為異常。
- 當異常被觸發時,通常會發生:
- 當前代碼狀態被保存
- 代碼執行被切換到預定義的異常處理器函數
- 根據情況,處理器也許會從保存的代碼狀態重新開始執行代碼,終止腳本執行,或從代碼中另外的位置繼續執行腳本
- 當異常被拋出時,其后的代碼不會繼續執行,PHP 會嘗試查找匹配的 "catch" 代碼塊
- 如果異常沒有被捕獲,而且又沒用使用 set_exception_handler() 作相應的處理的話,那么將發生一個嚴重的錯誤(致命錯誤),並且輸出 "Uncaught Exception" (未捕獲異常)的錯誤消息
php系統自帶異常處理:Exception
header("Content-type:text/html;charset=utf-8");
try
{
//業務處理 錯誤時拋出異常。
$age = 130;
if ($age > 120) {
throw new Exception('代碼學堂www.uxuew.cn。',888);
}
}catch (Exception $e) {
$err = [
'code' => $e->getCode(),
'msg' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
];
echo json_encode($err);
}
//輸出:{"code":888,"msg":"\u5e74\u9f84\u4e0d\u80fd\u5927\u4e8e120\u5c81\u3002","file":"\/ceshi.php","line":11}
php自定義異常處理
header("Content-type:text/html;charset=utf-8");
class proException extends Exception
{
//根據業務需求,自定義方法
/**
* 獲取錯誤信息
* @param int $type 類型 1=json 2=數組
* @return array
*/
public function getErrorInfo($type = 2)
{
$err = [
'code' => $this->getCode(),
'msg' => $this->getMessage(),
'file' => $this->getFile(),
'line' => $this->getLine()
];
if ($type == 1) {
return json_encode($err);
}
return $err;
}
}
try
{
//業務處理 錯誤時拋出異常。
$site =$_SERVER['HTTP_HOST'] ;
if ($site == 'www.uxuew.cn') {
throw new proException('代碼學堂官網',999);
}
} catch (proException $e) {
$info = $e->getErrorInfo();
var_dump($info);
}
輸出:array(4){["code"]=>int(999) ["msg"]=>string(27)"代碼學堂官網" ["file"]=>string(17) "/ceshi.php" ["line"]=>int(53)}
php還可以捕捉多個異常
header("Content-type:text/html;charset=utf-8");
class proException extends Exception
{
//根據業務需求,自定義錯誤方法
/**
* 獲取錯誤信息
* @param int $type 類型 1=json 2=數組
* @return array
*/
public function getErrorInfo($type = 2)
{
$err = [
'code' => $this->getCode(),
'msg' => $this->getMessage(),
'file' => $this->getFile(),
'line' => $this->getLine()
];
if ($type == 1) {
return json_encode($err);
}
return $err;
}
}
try
{
if ($_GET['age'] > 100) {
throw new proException('自定義的異常處理', 1002);
} else {
throw new Exception('系統的異常處理', 1002);
}
} catch (proException $e) {
$info = $e->getErrorInfo();
var_dump($info);//自定義異常處理
} catch (Exception $e) {
echo $e->getMessage();//系統異常處理
}
設置頂層異常處理器 (Top Level Exception Handler)
- set_exception_handler() 函數可設置處理所有未捕獲異常的用戶定義函數
function myException($exception)
{
echo "Exception: " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
- 在上面的代碼中,不存在 "catch" 代碼塊,而是觸發頂層的異常處理程序。應該使用此函數來捕獲所有未被捕獲的異常
php錯誤處理
- 在創建腳本和 web 應用程序時,錯誤處理是一個重要的部分。如果您的代碼缺少錯誤檢測編碼,那么程序看上去很不專業,也為安全風險敞開了大門
- 如果在本地程序調試時出現系統致命性錯誤可以設置error_reporting(E_ALL)來顯示所有錯誤信息,但在服務器中我們是不能這樣做的,這樣很容易暴露系統信息,那么我們要如何處理系統錯誤呢
- 我們可以自定義系統報錯函數:
- set_error_handler('errorHandler',E_ALL | E_STRICT) //設置錯誤處理器函數errorHandler,可以配合error_log函數實現日志記錄功能
- 參數:
- errorhandler 必需。規定用戶錯誤處理函數的名稱。
- E_ALL|E_STRICT 可選。規定顯示何種錯誤報告級別的用戶定義錯誤。默認是 "E_ALL"。
- 注:
- E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING是不會被這個句柄處理的,也就是會用最原始的方式顯示出來。不過出現這些錯誤都是編譯或PHP內核出錯,在通常情況下不會發生
- 使用set_error_handler()后,error_reporting()將會失效。也就是所有的錯誤(除上述的錯誤)都會交給自定義的函數處理
- 捕獲系統致命性錯誤:
- error_get_last() //獲取最后一次發生錯誤信息
- register_shutdown_function('fatalErrorHandler') //在腳本停止執行時注冊一個回調函數
- 注:通過以上兩個函數我們用可以監控系統致命性錯誤,比如服務器500錯誤,然后並記錄到日志文件中
- 代碼實例:
//禁止錯誤輸出
error_reporting(0);
//設置錯誤處理器
set_error_handler('errorHandler');
//在腳本結束時運行的函數
register_shutdown_function('fatalErrorHandler');
/**
* 錯誤處理
* @param int $err_no 錯誤代碼
* @param string $err_msg 錯誤信息
* @param string $err_file 錯誤文件
* @param int $err_line 錯誤行號
* @return string
*/
function errorHandler($err_no = 0, $err_msg = '', $err_file = '', $err_line = 0)
{
$log = [
'['.date('Y-m-d h-i-s').']',
'|',
$err_no,
'|',
$err_msg,
'|',
$err_file,
'|',
$err_line
];
$log_path = '/data/mi/test.txt';
error_log(implode(' ',$log)."\r\n",3, $log_path);
//echo implode(' ',$log)."";
}
/**
* 捕捉致命錯誤
* @return string
*/
function fatalErrorHandler() {
$e = error_get_last();
switch ($e['type']) {
case 1:
errorHandler($e['type'], $e['message'], $e['file'], $e['line']);
break;
}
}
class DemoClass_1
{
public function index()
{
//這里發生一個警告錯誤,出發errorHandler
echo $undefinedVarible;
}
}
$demo_1 = new DemoClass_1();
//這里發生一個警告錯誤,被errorHandler 捕獲
$demo_1->index();
//發生致命錯誤,腳本停止運行觸發 fatalErrorHandler
$demo_2 = new DemoClass_2();
$demo_2->index();
[2016-08-07 09-01-34] | 8 | Undefined variable: undefinedVarible | /data/mi/demo.php | 126
[2016-08-07 09-01-34] | 1 | Class 'DemoClass_2' not found | /data/mi/demo.php | 134
- 備注:
- register_shutdown_function 也可以用於API調試中,記錄每次請求值和返回值,方便調試
- 利用 “|” 分割的好處是,便於利用 awk 對日志進行分割處理