欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

php異常與錯誤處理機(jī)制概念及使用介紹

 更新時間:2022年09月14日 09:04:23   作者:whynogome  
在php中,可以利用異常處理類“Exception”中內(nèi)置的各種成員函數(shù)來獲取并返回異常數(shù)據(jù),例如getMessage()函數(shù)就可以返回異常的消息內(nèi)容;也可以通過“try?catch”語句和“throw”關(guān)鍵字來捕獲程序中的異常

基本概念

異常(exception)

程序執(zhí)行過程中,出現(xiàn)的不符預(yù)定業(yè)務(wù)邏輯和流程的,程序員可預(yù)測并提前寫好處理程序的一種情況

錯誤(error)

代碼本身的錯誤導(dǎo)致的程序運行失敗

標(biāo)準(zhǔn)異常處理

通過異常的定義,我們知道php中的異常是程序員提前預(yù)知并手動拋出的。

php通過try{}catch(){},配合Exception類,拋出并接收異常,實現(xiàn)異常的基本使用,如下

示例1

try{
	$param = $_GET['param'];
	if(empty($param))	throw new Exception('非法參數(shù)');
	//EmailException PhoneException 為自定義的異常類
	if(empty($param['email'])) throw new EmailException('郵件為空');
	if(empty($param['phone')) throw new PhoneException('手機(jī)號為空');
	$last_number = $prams[10];
}catch(EmailException $e1){
	echo $e1->getMessage();die();
}catch(PhoneException $e2){
	echo $e2->getMessage();die();
}catch(Exception $e3){
	echo $e3->getMessage();die();
}

自定義異常處理

當(dāng)代碼中有多處異常需要拋出時,我們可以不必每次都使用try…catch處理,完全可以統(tǒng)一處理。這時我們可以用set_exception_handler 方法,注冊一個異常監(jiān)聽方法。當(dāng)有異常拋出時,且沒有被 try … catch 捕獲處理的話,此時系統(tǒng)會檢查上下文是否注冊了 set_exception_handler。

如果未注冊 則進(jìn)入 PHP 標(biāo)準(zhǔn)錯誤處理 致命錯誤退出執(zhí)行。

如果已注冊 則進(jìn)入 set_exception_handler 處理 程序依然會退出執(zhí)行。

故建強(qiáng)烈議將需要后續(xù)處理的異常的執(zhí)行邏輯放入 try … catch 中執(zhí)行。

將會阻斷流程的異常使用set_exception_handler處理

// 捕獲異常后程序會退出執(zhí)行
set_exception_handler(function ($exception) {
    echo $exception->getMessage();
    // 此處程序會退出執(zhí)行 異常到此結(jié)束 并不會交給 PHP 標(biāo)準(zhǔn)異常處理
});
throw new Exception('hello world!');
echo 'will i be executed?';

異常處理最佳使用場景

雖說異常是對不符合預(yù)期業(yè)務(wù)邏輯的處理,但并不是在所有業(yè)務(wù)流程判斷中都使用異常處理,這會導(dǎo)致代碼臃腫,那么什么時候使用異常處理最佳呢

控制異常代碼影響范圍

當(dāng)業(yè)務(wù)流程不在預(yù)期內(nèi)時,且會對后續(xù)代碼造成影響時。通過try…catch 及時拋出并處理異常,把異常造成的邏輯中斷破壞降低到最小范圍。上面實例代碼就是這種情況。

保證數(shù)據(jù)統(tǒng)一性

當(dāng)對相關(guān)聯(lián)的數(shù)據(jù)進(jìn)行操作,若有成功又失敗,會造成關(guān)聯(lián)數(shù)據(jù)之間的信息不同步。進(jìn)行該類操作時,一旦有一個數(shù)據(jù)操作失敗就拋出異常,然后把已操作的數(shù)據(jù)進(jìn)行回滾。

典型的使用案例就是對數(shù)據(jù)庫的事務(wù)操作,一般都放在try…catch中

錯誤處理

錯誤等級定義

php定義了一些錯誤等級常量,如下

名稱說明舉例
E_ERROR1致命的運行時錯誤(程序終止)。這類錯誤一般是不可恢復(fù)的情況,例如內(nèi)存分配導(dǎo)致的問題。后果是導(dǎo)致腳本終止不再繼續(xù)運行。使用了未定義方法、類、方法參數(shù)不匹配等情況
E_WARNING2運行時警告 (非致命錯誤)。僅給出提示信息,但是腳本不會終止運行。除數(shù)為0等比較嚴(yán)重的錯誤
E_PARSE4編譯時語法解析錯誤(程序終止)。解析錯誤僅僅由分析器產(chǎn)生少了分號、括號等語法錯誤
E_NOTICE8運行時通知。表示腳本遇到可能會表現(xiàn)為錯誤的情況,但是在可以正常運行的腳本里面也可能會有類似的通知。使用了未定義的變量或不存在的偏移量
E_CORE_ERROR16在PHP初始化啟動過程中發(fā)生的致命錯誤(程序終止)。該錯誤類似E_ERROR,但是是由PHP引擎核心產(chǎn)生的例如php.ini文件配置錯誤
E_CORE_WARNING32PHP初始化啟動過程中發(fā)生的警告 (非致命錯誤) 。類似 E_WARNING,但是是由PHP引擎核心產(chǎn)生的例如php.ini文件配置異常
E_COMPILE_ERROR64致命編譯時錯誤(程序終止)。類似E_ERROR, 但是是由Zend腳本引擎產(chǎn)生的 
E_COMPILE_WARNING128編譯時警告 (非致命錯誤)。類似 E_WARNING,但是是由Zend腳本引擎產(chǎn)生的 
E_USER_ERROR256用戶產(chǎn)生的錯誤信息(程序終止)。類似 E_ERROR, 但是是由用戶自己在代碼中使用PHP函數(shù) trigger_error()來產(chǎn)生的 
E_USER_WARNING512用戶產(chǎn)生的警告信息。類似 E_WARNING, 但是是由用戶自己在代碼中使用PHP函數(shù) trigger_error()來產(chǎn)生的 
E_USER_NOTICE1024用戶產(chǎn)生的通知信息。類似 E_NOTICE, 但是是由用戶自己在代碼中使用PHP函數(shù) trigger_error()來產(chǎn)生的 
E_STRICT2048啟用 PHP 對代碼的修改建議,以確保代碼具有最佳的互操作性和向前兼容性 
E_RECOVERABLE_ERROR4096可被捕捉的致命錯誤。 它表示發(fā)生了一個可能非常危險的錯誤,但是還沒有導(dǎo)致PHP引擎處于不穩(wěn)定的狀態(tài)。 如果該錯誤沒有被用戶自定義句柄捕獲,將成為一個 E_ERROR 從而腳本會終止運行 
E_DEPRECATED8192運行時通知。啟用后將會對在未來版本中可能無法正常工作的代碼給出警告 
E_USER_DEPRECATED16384用戶產(chǎn)少的警告信息。 類似 E_DEPRECATED, 但是是由用戶自己在代碼中使用PHP函數(shù) trigger_error()來產(chǎn)生的 
E_ALL30719E_STRICT出外的所有錯誤和警告信息 

經(jīng)常出現(xiàn)的錯誤提示一般是1,2,4,8幾種,E_CORE_*和E_CMMPILE_*級別的錯誤很少會出現(xiàn)

標(biāo)準(zhǔn)錯誤處理

標(biāo)準(zhǔn)錯誤處理是指針對程序執(zhí)行過程中出現(xiàn)的錯誤,用戶未自主處理時,php會使用標(biāo)準(zhǔn)模式展示這些錯誤

開啟標(biāo)準(zhǔn)錯誤提示

ini_set(‘display_errors’,‘on’); //off是關(guān)閉

設(shè)置標(biāo)準(zhǔn)錯誤提示等級

error_reporting(E_ALL | E_STRICT); //表示所有等級錯誤都為提示,可自行選擇需要提示的錯誤等級

默認(rèn)狀態(tài)下,php沒有開啟錯誤提示。當(dāng)有致命錯誤導(dǎo)致程序終止,且用戶也未捕獲錯誤時,會返回一個500錯誤

但當(dāng)開啟了標(biāo)準(zhǔn)錯誤提示后,會打印出錯誤信息

自主處理非致命錯誤

若我們想要自主捕獲錯誤并處理,可以使用set_error_handler方法,注冊一個處理錯誤的方法,如下

set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
	//方法內(nèi)可以自行處理要打印的異常信息
	echo '這是一個自主處理的異常,異常編號:'.$error_no;
	// 若return false,程序不會終止,錯誤會繼續(xù)遞交給 PHP 標(biāo)準(zhǔn)錯誤處理。否則結(jié)束程序
	//return false;
})

使用自定義錯誤處理的話,標(biāo)準(zhǔn)錯誤無效,因我們注冊的方法接管了標(biāo)準(zhǔn)錯誤處理

但是,set_error_handler并不能捕獲所有錯誤

  • 可以捕獲: E_WARNING & E_NOTICE & E_DEPRCATED & E_USER_* & 部分 E_STRICT 級的錯誤。
  • 無法捕獲: E_ERROR & E_PARSE & E_CORE_* & E_COMPLIE_* 級的錯誤。

自主處理致命錯誤

那么我們該如何獲取致命級別的錯誤呢

如果我們跟著文章設(shè)置了標(biāo)準(zhǔn)錯誤,并編寫代碼測試后,會發(fā)現(xiàn)當(dāng)代碼有致命錯誤時,并沒錯誤輸出,而是直接500錯誤,如下,我們新建一個error.php文件

<?php
ini_set('display_errors','off');
error_reporting(E_ALL | E_STRICT);
echo "aaa"

代碼少了分號,語法錯誤。當(dāng)時直接返回500,這是為什么呢。這個涉及到了php的程序的編譯和執(zhí)行問題

PHP是腳本語言,在執(zhí)行代碼時需要先進(jìn)行一系列的編譯處理,才能執(zhí)行。在文件編譯階段,對代碼語法進(jìn)行了校驗,但這個時候代碼未執(zhí)行,所以文件開頭的動態(tài)配置是沒有意義的。編譯時判斷語法錯誤,腳本直接停止了運行。直接調(diào)用了php.ini的默認(rèn)配置,不顯示錯誤信息。這就是為什么在php.ini配置可以生效,動態(tài)配置無效的原因。

為了解決這個問題,我們要保設(shè)置證標(biāo)準(zhǔn)錯誤開啟的文件正確,能夠被正常編譯執(zhí)行,配置才能生效。

我們包error.php最后一行代碼刪除。然后新建一個index.php文件,在文件中引入error.php即可,如下

index.php

<?php 
include "error.php";
echo "aaa"

再次執(zhí)行后,頁面輸出了錯誤信息。

這是因為index.php文件在編譯到錯誤代碼報錯前,先編譯了引入的error.php文件,error文件被正確執(zhí)行,配置生效。

根據(jù)php這個特性,我們要捕獲致命級錯誤,就需要捕獲錯誤的代碼不會被錯誤代碼影響到。try…catch就是一個完美的無措容器,我們可以在try引入如錯誤代碼(不能直接寫錯誤代碼,會編譯錯誤),在catch中捕獲錯誤,如下

try{
    include 'index.php';
} catch (\ErrorException $errorException) {
    // 捕獲錯誤異常
    echo 'ErrorException: ' . $errorException . PHP_EOL;
} catch (\Exception $exception) {
    // 捕獲異常
    echo 'Exception: ' . $exception . PHP_EOL;
} catch (\TypeError $typeError) {
    // 捕獲類型錯誤 返回值/參數(shù)不正確
    //var_dump($typeError);
    echo 'Type Error: ' . $typeError->getFile() . PHP_EOL;
} catch (\ParseError $parseError) {
    // 捕獲解析錯誤 語法錯誤
    echo 'Parse Error: ' . $parseError . PHP_EOL;
} catch (\DivisionByZeroError $divisionByZeroError) {
    // 除 0 無法捕獲 但 除 0 取余可以捕獲 = = 很無奈
    echo 'Division By Zero Error: ' . $divisionByZeroError . PHP_EOL;
} catch (\Error $error) {
    // 基本錯誤
    echo 'Error: ' . $error . PHP_EOL;
}

拋出自定義錯誤

trigger_error 用來觸發(fā)用戶級別的自定義錯誤

set_error_handler 和 標(biāo)準(zhǔn)錯誤 都能捕獲到該錯誤

trigger("報錯信息",E_USER_NOTICE);//默認(rèn)錯誤等級為E_USER_NOTICE

支持E_USER_NOTICE,E_USER_WARNING,E_USER_DEPRECATED,E_USER_ERROR 四個錯誤類型的拋出

E_USER_ERROR 級別的錯誤如果被 PHP 標(biāo)準(zhǔn)錯誤處理 捕獲,腳本也會退出執(zhí)行

到此這篇關(guān)于php異常與錯誤處理機(jī)制概念及使用介紹的文章就介紹到這了,更多相關(guān)php異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論