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

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

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

基本概念

異常(exception)

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

錯(cuò)誤(error)

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

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

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

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

示例1

try{
	$param = $_GET['param'];
	if(empty($param))	throw new Exception('非法參數(shù)');
	//EmailException PhoneException 為自定義的異常類(lèi)
	if(empty($param['email'])) throw new EmailException('郵件為空');
	if(empty($param['phone')) throw new PhoneException('手機(jī)號(hào)為空');
	$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)代碼中有多處異常需要拋出時(shí),我們可以不必每次都使用try…catch處理,完全可以統(tǒng)一處理。這時(shí)我們可以用set_exception_handler 方法,注冊(cè)一個(gè)異常監(jiān)聽(tīng)方法。當(dāng)有異常拋出時(shí),且沒(méi)有被 try … catch 捕獲處理的話,此時(shí)系統(tǒng)會(huì)檢查上下文是否注冊(cè)了 set_exception_handler。

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

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

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

將會(huì)阻斷流程的異常使用set_exception_handler處理

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

異常處理最佳使用場(chǎng)景

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

控制異常代碼影響范圍

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

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

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

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

錯(cuò)誤處理

錯(cuò)誤等級(jí)定義

php定義了一些錯(cuò)誤等級(jí)常量,如下

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

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

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

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

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

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

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

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

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

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

自主處理非致命錯(cuò)誤

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

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

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

但是,set_error_handler并不能捕獲所有錯(cuò)誤

  • 可以捕獲: E_WARNING & E_NOTICE & E_DEPRCATED & E_USER_* & 部分 E_STRICT 級(jí)的錯(cuò)誤。
  • 無(wú)法捕獲: E_ERROR & E_PARSE & E_CORE_* & E_COMPLIE_* 級(jí)的錯(cuò)誤。

自主處理致命錯(cuò)誤

那么我們?cè)撊绾潍@取致命級(jí)別的錯(cuò)誤呢

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

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

代碼少了分號(hào),語(yǔ)法錯(cuò)誤。當(dāng)時(shí)直接返回500,這是為什么呢。這個(gè)涉及到了php的程序的編譯和執(zhí)行問(wèn)題

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

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

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

index.php

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

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

這是因?yàn)閕ndex.php文件在編譯到錯(cuò)誤代碼報(bào)錯(cuò)前,先編譯了引入的error.php文件,error文件被正確執(zhí)行,配置生效。

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

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

拋出自定義錯(cuò)誤

trigger_error 用來(lái)觸發(fā)用戶(hù)級(jí)別的自定義錯(cuò)誤

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

trigger("報(bào)錯(cuò)信息",E_USER_NOTICE);//默認(rèn)錯(cuò)誤等級(jí)為E_USER_NOTICE

支持E_USER_NOTICE,E_USER_WARNING,E_USER_DEPRECATED,E_USER_ERROR 四個(gè)錯(cuò)誤類(lèi)型的拋出

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

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

相關(guān)文章

最新評(píng)論