那些年,PHPer遇到的錯誤與異常:上篇之錯誤

1、PHP中錯誤模塊簡介

     PHP錯誤與異常是兩個不一樣的概念php

1.1 錯誤類型

  1. 語法錯誤,如少分號
  2. 環境錯誤,如權限、打開文件失敗、數據庫服務器不可用
  3. 邏輯錯誤,如a==b 寫成了a=b

1.2 PHP常見錯誤級別

  1. Depracated最低級別的錯誤 (deprecated不建議,不推薦,如老版本的正則ereg()函數換掉便可,並不影響PHP的執行)
  2. Notice通知級別的錯誤(語法不恰當致使的,不影響PHP的正常運行,如打印一個未定義的變量,因此咱們一開始就要養成良好的書寫規範)
  3. Warning警告級別的錯誤(必須修改代碼)
  4. Fatal error致命級別的錯誤,程序會中止
  5. Parse error語法解析錯誤,在代碼運行前檢查,將沒法執行代碼
  6. E_USER_相關的錯誤 由用戶定義的錯誤,手動拋出錯誤時會用到

1.3 如何設置錯誤級別

1.3.1 php.ini配置文件

error_reporting=E_ALL & ~E_NOTICE # 顯示全部但不顯示提醒錯誤
display_errors = Off|On # 是否顯示錯誤,線上後關閉提升用戶體驗

1.3.2 動態設置

error_reporting() # 專業php錯誤處理設置函數,動態設置錯誤級別
error_reporting(0) # 不顯示全部錯誤,可是解析parse語法錯誤會顯示
error_reporting(-1) # 顯示全部錯誤
Error_reporting(E_ALL|~E_WARING) # 除了警告錯誤之外的錯誤級別都報告

1.3.3 運行時設置配置選項的值

ini_set(option,value)

ini_set(error_reporting,0)
ini_set(error_reporting,-1)
ini_set(error_reporting,E_ALL)
ini_set(display_errors,0)
ini_set(display_errors,OFF/0)
error_reporting(-1);

14. trigger_error手動觸發錯發

    @錯誤抑制符,放在行首不顯示該行錯誤數據庫

    手動拋出自定義錯誤信息:trigger_error('錯誤提示內容',E_USER_NOTICE)segmentfault

    clipboard.png

  錯誤級別:瀏覽器

E_USER_NOTICE # 繼續執行(通知級別)
E_USER_WARNING # 繼續執行(警告錯誤)
E_USER_ERROR # 程序再也不執行(致命錯誤)

2、處理PHP中的錯誤

2.1 將錯誤日誌保存在指定文件中

ini_set('display_errors','off') # 不顯示錯誤給用戶
ini_set("error_log","c:\error.log");       
error_reporting(-1); # 顯示全部錯誤

2.2 錯誤日誌保存在系統日誌中

ini_set("error_log", 'syslog')

2.3 將錯誤日誌發送到郵件

error_log("this is a errormsg",1,xxxxx@qq.com);

3、自定義錯誤處理器

3.1 set_error_handler自定義錯誤處理

set_error_handler("自定義函數名",'錯誤級別(選填)') # 設置一個用戶定義的錯誤處理函數    

restore_error_handler(); # 回收(取消自定義錯誤函數接管php系統錯誤)

     clipboard.png

3.2 自定義錯誤處理器

class MyErrorHandler{
    //錯誤信息
    public $message = '';
    //錯誤文件
    public $filename = '';
    //錯誤行號
    public $line = 0;
    //額外信息
    public $vars = array();
    protected $_noticelog = 'G:\notice\noticeLog.log';

    public function __construct($message, $filename, $line, $vars)
    {
        $this->message = $message;
        $this->filename = $filename;
        $this->line = $line;
        $this->vars = $vars;
    }
    //根據不一樣錯誤級別對應不一樣操做
    //遵循handler錯誤處理原則,errno:錯誤代碼,line:錯誤行號
    public static function deal($errno,$errmsg,$filename,$line,$vars)
    {
        $self = new self($errmsg,$filename,$line,$vars);
        switch ($errno)
        {
            case E_USER_ERROR://致命級別
                return $self->dealError();
                break;
            case E_USER_WARNING://警告級別
            case E_WARNING:
                return $self->dealWarning();
                break;
            case E_NOTICE://通知級別
            case E_USER_NOTICE:
                return $self->dealNotice();
                break;
            default:
                return false;
        }
    }

    /**
     * 如何處理致命錯誤
     */
    public function dealError()
    {
        //開啓內存緩衝
        ob_start();
        //回溯上一條信息
        debug_print_backtrace();
        $backtrace = ob_get_flush();
        $errorMsg = <<<EOF
        出現了致命錯誤,以下:
產生錯誤的文件:{$this->filename}
產生錯誤的信息:{$this->message}
產生錯誤的行號:{$this->line}
追蹤信息:{$backtrace}
EOF;
//    error_log($errorMsg,1,'xxxx@qq.com');
        error_log($errorMsg,3,$this->_noticelog);
        exit(1);
    }

    /**
     * 如何處理警告錯誤
     */
    public function dealWarning()
    {
        $errorMsg = <<<EOF
        出現了警告錯誤,以下:
產生警告的文件:{$this->filename}
產生警告的信息:{$this->message}
產生警告的行號:{$this->line}
EOF;
//        return error_log($errorMsg,1,'xxx@qq.com');
        return error_log($errorMsg,3,$this->_noticelog);
    }

    /**
     * 如何處理通知錯誤
     */
    public function dealNotice()
    {
        $datetime = date('Y-m-d H:i:s',time());
        $errorMsg = <<<EOF
        出現了通知錯誤,以下:
產生通知的文件:{$this->filename}
產生通知的信息:{$this->message}
產生通知的行號:{$this->line}
產生通知的時間:{$datetime}
EOF;
        return error_log($errorMsg,3,$this->_noticelog);
    }
}

3.3 錯誤處理器測試

require_once 'MyErrorHandler.php';
error_reporting(-1);
//使用MyErrorHandler類直接調用deal方法
/**
 * set_error_handler(array(類名/new 類名,方法名));
 * set_error_handler(函數名);
 */
set_error_handler(array('MyErrorHandler','deal'));

//通知級別錯誤
echo $test;
//警告級別錯誤
settype($var,'king');
//致命錯誤
//test();

//總結:手動拋出的信息會被顯示在瀏覽器
trigger_error('我是手動拋出的致命錯誤',E_USER_ERROR);

//自定義錯誤處理器會繼續執行一下代碼,而手動拋出的錯誤信息不會繼續執行
echo 'this is a test ';

3.4 register_shutdown_function函數使用

     clipboard.png

     使用場景:服務器

  1. 頁面強制被中止
  2. 程序代碼意外終止或超時

     clipboard.png

     register_shutdown_function()函數是從內存中調用的,也就是PHP語句執行完以後(頁面已不存在了)再調用這個函數,因此寫路徑的時候已經脫離這個腳本了,因此file_put_contents()路徑要用絕對路徑函數

error_get_last # 獲得最後產生的錯誤

     注意:若是在register_shutdown_function() 以前有die/exit則不會被執行測試

下一篇:那些年,PHPer遇到的錯誤與異常:下篇之異常

參考課程視頻:那些年你遇到的錯誤與異常ui

相關文章
相關標籤/搜索