php的異常和處理

常見錯誤處理類型

  • 語法錯誤php

  • 環境錯誤html

  • 邏輯錯誤apache

常見錯誤級別

  • Deprecated 最低級別的錯誤windows

    • 不推薦,不建議,使用一些過時函數的時候會出現,程序繼續執行數組

  • Notice 通知級別的錯誤服務器

    • 使用一些未定義變量、常量或者數組key沒有加引號的時候會出現,程序繼續執行函數

  • Waning 警告級別的錯誤this

    • 程序出問題了,須要修改代碼!!!程序繼續執行debug

  • Fatal Error 錯誤級別的錯誤rest

    • 程序直接報錯,須要修改代碼!!!中斷程序執行

  • parse error 語法解析錯誤

    • 語法檢查階段報錯,須要修改代碼!!!中斷程序執行

  • E_USER_相關的錯誤

    • 用戶定義的錯誤,用戶手動拋出錯誤,進行自定義錯誤處理

PHP配置文件和錯誤相關選項

設置錯誤級別
一、經過修改php.ini文件設置錯誤級別,靜態設置,須要重啓apache
// error_reporting = E_ALL&~E_NOTICE; //顯示全部錯誤,除了E_NOTICE級別
// display_errors = 1; //線下開啓,先上關閉

二、經過error_reporting()函數設置,動態設置
// error_reporting(E_ALL&~E_NOTICE); //顯示全部錯誤,除了E_NOTICE級別
// error_reporting(0); //屏蔽全部錯誤,只會顯示語法解析錯誤
// erorr_reporting(-1); //顯示全部錯誤

三、經過ini_set()函數進行運行時設置,動態設置
// ini_set('error_reporting',0);
// ini_set('error_reporting',-1);
// ini_set('display_errors',0);

使用triggerr_error進行錯誤拋出

<?php
header('content-type:text/html;charset=utf-8');

$num1=1;
$num2='xxx';
if ( (!is_numeric($num1) || !is_numeric($num2)) ) {

    //通知級別,代碼繼續執行
    //echo trigger_error('數值必須爲整型!',E_USER_NOTICE); 
    
    //警告級別,代碼繼續執行
    //echo trigger_error('數值必須爲整型!',E_USER_WARNING); 
    
    //錯誤級別,代碼中斷
    echo trigger_error('數值必須爲整型!',E_USER_ERROR); 

}else{
    echo $num1+$num2;
}

echo '<br />代碼繼續執行';

記錄錯誤

配置php.ini腳本設置記錄錯誤
log_errors = On //是否將產生錯誤信息記錄到日誌或者error_log中
;error_log = syslog //設置腳本錯誤將記錄到系統日誌中
log_errors_max_len = 1024 //設置錯誤報錯最大值,單位字節
ignore_repeated_errors = Off //是否忽略重複的錯誤信息
ignore_repeated_source = Off //是否忽略重複錯誤消息的來源
track_errors = On //若是開啓,最後一個錯誤將永遠保存在$php_errormsg中

將錯誤記錄到指定的文件中

<?php
//運行時設置錯誤處理
ini_set('display_errors','off');
ini_set('error_log','D:\logs\error.log');
//設置錯誤輸出
error_reporting(-1);

echo $test; //NOTICE
echo '<hr />';

settype($var,'king'); //Warning
echo '<hr />';

test(); //Fatal error

將日誌文件保存到系統日誌中

<?php
error_reporting(-1);
ini_set('display_errors',0);
ini_set('log_errors',1);
ini_set('error_log','syslog');
//該記錄方式,在windows中須要去,計算機管理-》事件查看器-》自定義視圖中查找php5.4.0的log日誌
openlog('PHP5.4.0',LOG_PID,LOG_SYSLOG);
syslog(LOG_ERR,'this is syslog !!!daye:'.date('Y/m/d H:i:s'));
closelog();

將錯誤以郵件形式發送
一、首先須要配置郵件服務器!
二、去php.ini中配置郵件參數
三、寫代碼

error_log('當前系統被人攻擊!產生錯誤!',1,'87399497@qq.com');

error_log函數使用

error_log($msg); //傳入錯誤記錄,須要與error_log配置使用

如何使用Set_error_handler()

<?php

header('content-type:text/html;charset=utf-8');

//-1表明顯示全部的錯誤警告
error_reporting(-1);

/**
 * 自定義一個錯誤處理
 * @param  [type] $errno  [錯誤級別]
 * @param  [type] $errmsg [錯誤信息]
 * @param  [type] $file   [錯誤文件]
 * @param  [type] $line   [錯誤行號]
 * @return [type]         [description]
 */
function customer_error($errno,$errmsg,$file,$line){
    echo "<b>錯誤代碼:</b>[{$errno}] {$errmsg} <br/>".PHP_EOL;
    echo "<b>錯誤行號:</b>{$file}文件中的第 {$line} <br/>".PHP_EOL;
    echo "<b>PHP版本:</b>".PHP_VERSION."(".PHP_OS.") <br/>".PHP_EOL;
    //注意:若是自定義錯誤處理捕獲了,代碼仍是會執行,若是不想被執行,須要die掉!!!
    //die;
}

//設置自定義錯誤處理
set_error_handler('customer_error');

//輸出一個未定義變量的警告
echo $test;
echo '<hr/>';
//原生出錯
//Notice: Undefined variable: test in D:\phpStudy\WWW\example\index.php on line 26

//自定義出錯
//錯誤代碼:[8] Undefined variable: test 
//錯誤行號:D:\phpStudy\WWW\example\index.php文件中的第 26 
//PHP版本:5.3.29(WINNT) 


//沒法捕獲一個致命錯誤Fatal error,會切換到原生出錯
//test();

//手動拋出一個錯誤,被自定義的錯誤處理捕獲
trigger_error('this is a test of error',E_USER_ERROR);
echo 'contiune';
echo '<hr/>';

//錯誤代碼:[256] this is a test of error 
//錯誤行號:D:\phpStudy\WWW\example\index.php文件中的第 43 
//PHP版本:5.3.29(WINNT) 
//contiune


//取消自定義錯誤處理,將會從新適應PHP原生的錯誤處理
restore_error_handler();
echo $tt;
echo '<hr />';

//Notice: Undefined variable: tt in D:\phpStudy\WWW\example\index.php on line 49


//從新掛載自定義錯誤處理
//除了NOTICE級別的交給系統處理,剩下的所有使用customer_error自定義的錯誤處理
set_error_handler('customer_error',E_ALL&~E_NOTICE);

echo $asc; //E_NOTICE級別,系統的錯誤處理
settype($var,'king'); //E_WARNING級別,使用自定義的錯誤處理

//Notice: Undefined variable: asc in D:\phpStudy\WWW\example\index.php on line 65

//錯誤代碼:[2] settype() [function.settype]: Invalid type 
//錯誤行號:D:\phpStudy\WWW\example\index.php文件中的第 66 
//PHP版本:5.3.29(WINNT)

自定義一個錯誤處理器

<?php

class MyErrorHandler{
    
    public $msg='';
    public $filename='';
    public $line=0;
    public $vars=array();

    public function __construct($msg,$filename,$line,$vars){
        $this->msg = $msg;
        $this->filename = $filename;
        $this->line = $line;
        $this->vars = $vars;
    }

    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;
                break;
        }
    }

    /**
     * 處理致命錯誤
     * @return [type] [description]
     */
    public function dealError(){
        ob_start();
        debug_print_backtrace();
        $backtrace = ob_get_flush();
        $errmsg = <<<EOF
出現了致命錯誤,以下:
產生錯誤的文件:{$this->filename}
產生錯誤的信息:{$this->msg}
產生錯誤的行號:{$this->line}
追蹤信息:{$backtrace}
EOF;
        //發送郵件的錯誤日誌
        //error_log($errmsg,1,'87399497@qq.com');
        //記錄到錯誤日誌
        error_log($errmsg,3,'D:/logs/customer_error.log');
        exit(1);
    }

    /**
     * 處理警告錯誤
     * @return [type] [description]
     */
    public function dealWarning(){
        $errmsg = <<<EOF
出現了警告錯誤,以下:
產生警告的文件:{$this->filename}
產生警告的信息:{$this->msg}
產生警告的行號:{$this->line}
EOF;
        error_log($errmsg,3,'D:/logs/customer_warning.log');
    }

    /**
     * 處理通知級別的錯誤
     * @return [type] [description]
     */
    public function dealNotice(){
        $date = date('Y-m-d H:i:s',time());
        $errmsg = <<<EOF
出現了通知錯誤,以下:
產生錯誤的文件:{$this->filename}
產生錯誤的信息:{$this->msg}
產生錯誤的行號:{$this->line}
產生通知的時間:{$date}
EOF;
        error_log($errmsg,3,'D:/logs/customer_notice.log');
    }
}



//顯示全部錯誤
error_reporting(-1);

//設置自定義錯誤,使用傳入類和方法的方式
set_error_handler(array('MyErrorHandler','deal'));

//觸發NOTICE級別錯誤,會保存到log日誌中
echo $tt;

//手動觸發一個錯誤
trigger_error('手動拋出一個錯誤',E_USER_ERROR);

register_shutdown_function()函數

<?php 
//register_shutdown_function該函數將會在PHP執行關閉時調用
//使用場景
//一、頁面強制中止
//二、代碼意外終止

class Showdown{
    public static function endScript(){
        if (error_get_last()){
            echo '<pre>';
            error_get_last();
            echo '</pre>';
            
            //由於register_shutdown_function調用該函數的時候,是代碼終止,脫離當前PHP上下文環境了
            //因此$filename的路徑要寫決定路徑!!!
            file_put_contents('D:\logs\register_shutdown_function.log', error_get_last());
            
            die('endScript');
        }
    }
}

//特別聲明!若是有die或exit在註冊錯誤處理以前,那麼將不會註冊錯誤處理

register_shutdown_function(array('Showdown','endScript'));

echo md6();

錯誤抑制符

@settype($var,'longjq'); //無變量$var,使用@符號進行抑制錯誤輸出

錯誤級別

http://www.w3school.com.cn/php/php_ref_error.asp

相關文章
相關標籤/搜索