php7中的異常和錯誤處理

在PHP7.*版本中,一些Error和Exception可以通過try catch語句捕獲到
可捕獲的異常/錯誤大致有以下三種:

  1. Error:PHP內核拋出錯誤的專用類型, 如類不存在, 函數不存在, 函數參數錯誤, 都會拋出此類型的錯誤,
    PHP代碼中不應該使用Error類來作爲異常拋出

  2. Exception:應用開發者應該使用的異常基類

  3. 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"}
發佈了101 篇原創文章 · 獲贊 27 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章