在PHP7.*版本中,一些Error和Exception可以通過try catch語句捕獲到
可捕獲的異常/錯誤大致有以下三種:
-
Error:PHP內核拋出錯誤的專用類型, 如類不存在, 函數不存在, 函數參數錯誤, 都會拋出此類型的錯誤,
PHP代碼中不應該使用Error類來作爲異常拋出 -
Exception:應用開發者應該使用的異常基類
-
ErrorException:此異常基類專門負責將PHP的Warning/Notice等信息通過set_error_handler轉換成異常,
PHP未來的規劃必然是將所有的Warning/Notice轉爲異常, 以便於PHP程序能夠更好更可控地處理各種錯誤
針對異常和錯誤,要用不同的方法來處理,儘量避免fatal error,一旦有這種嚴重錯誤,應該發報警郵件提醒。
<?php
echo 'arrive here 111<hr>';
error_reporting(E_ALL);
//在register_shutdown_function中可以捕獲到Fatal Error錯誤, 該語句應該放在文件前面
register_shutdown_function('shutdown_fun');
function testError()
{
ini_set('memory_limit', "2M");
$rows = [];
for ($i=1; $i<100000; ++$i) {
$row = ['username'=>'user'.sprintf('%6d',$i), 'userid'=>$i, 'tag'=>'年年歲歲花相似,歲歲年年人不同'];
$row['createtime'] = date('Y-m-d H:i:s');
$row['email'] = $row['username'].'@163.com';
$row['age'] = mt_rand(21,45);
$row['gander'] = (mt_rand(1,10000) %2 == 0)?'famale':'male';
$rows[] = $row;
}
print_r(count($rows));
}
try {
//調用不存在的方法時會捕獲到Error(這裏不是Exception),但不會進入到shutdown_fun中
test();
} catch (Error $e) {
echo 'in '.__FILE__.",222, error:".$e->getMessage()."<hr/>";
} catch(Exception $e) {
echo 'in '.__FILE__.",333, exception:".$e->getMessage()."<hr/>";
}
//上述try catch替代語法
/*try {
//調用不存在的方法時會捕獲到Error(這裏不是Exception),但不會進入到shutdown_fun中
test();
} catch (Throwable $e) {
echo 'in '.__FILE__.",334, error:".$e->getMessage()."<hr/>";
}*/
try {
/**
* PHP錯誤的一個重要級別, 如異常/錯誤未捕獲時, 內存不足時, 或是一些編譯期錯誤(繼承的類不存在),
* 將會以E_ERROR級別拋出一個Fatal Error, 是在程序發生不可回溯的錯誤時纔會觸發的,
* PHP程序無法捕獲這樣級別的一種錯誤, 只能通過register_shutdown_function在後續進行一些處理操作。
* 出現該錯誤時,程序會中斷。
*/
testError();
} catch (Error $e) {
echo 'in '.__FILE__.",444, error:".$e->getMessage()."<hr/>";
} catch(Exception $e) {
echo 'in '.__FILE__.",555, exception:".$e->getMessage()."<hr/>";
}
//記錄報錯詳情語句
function shutdown_fun() {
if(function_exists('error_get_last')){
$msg = error_get_last();
if(isset($msg['file'])&&!empty($msg['file'])){
$err_type = array(E_RECOVERABLE_ERROR,E_ERROR,E_CORE_ERROR,E_COMPILE_ERROR,E_USER_ERROR,E_USER_DEPRECATED);
$msg['servername'] = isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:'cli';
$msg['REQUEST_URI']= $msg['servername'].(isset($_SERVER['REQUEST_URI'])?$_SERVER['REQUEST_URI']:'');
$msg['POST'] = $_POST;
$msg['operator'] = isset($_SESSION['mastername'])?$_SESSION['mastername']:'system';
$msg['ip'] = isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'unknow';
$myinfo = date('Y-m-d H:i:s').' '.json_encode($msg);
file_put_contents('/tmp/error.log', $myinfo, FILE_APPEND);
}
}
}
最終的輸出結果:
而且在/tmp/error.log中會有新增的錯誤信息:
2019-12-24 14:41:51 {"type":1,"message":"Allowed memory size of 2097152 bytes exhausted (tried to allocate 4096 bytes)","file":"\/var\/www\/html\/site\/test_error.php","line":15,"servername":"192.168.56.102","REQUEST_URI":"192.168.56.102\/test_error.php","POST":[],"operator":"system","ip":"192.168.56.101"}