詳細解讀php的異常處理機制
異常機制
一.異常基本知識
1.定義:異常處理用於在指定的錯誤(異常)情況發生時改變指令碼的正常流程,這過程稱為異常.
2.基本用法:
try
{
//可能出現的錯誤(異常)程式碼
}
catch(Exception $e)
{
//自己處理:捕捉異常並處理,
//自己不處理:丟擲一個異常,即如下:
throw $e;
}
其中,Exception是異常類(php中定義好的一個類,具體參見php參考文件:語音參考->異常處理).它已經封裝好很多方法,常用如下:
function__construct($message = null, $code = 0);
final function
final function getCode(); // 返回異常程式碼
final function getFile(); // 返回發生異常的檔名
final function getLine(); // 返回發生異常的程式碼行號
final function getTrace(); // backtrace() 陣列
final function getTraceAsString();
/* 可過載的方法 */
function __toString(); // 可輸出的字串
3.入門案例
案例1:
<?php try{ adduser("weimin"); echo "adduser()如果出現異常,這句話就不會出現<br>"; updateuser("wly1"); echo "updateuser()如果出現異常,這句話就不會出現<br>"; } catch(Exception $e) { echo "error!".$e->getMessage(); //getMessage()為異常中一個函式,可返回異常資訊 } function adduser($username) { if($username=="weimin") { } else { throw new Exception("新增失敗");//丟擲異常,及返回一個異常 } } function updateuser($username) { if($username=="wly") { } else { throw new Exception("修改失敗");//丟擲異常 } } ?>
結果:
adduser()如果出現異常,這句話就不會出現
error!修改失敗
二.異常使用的注意事項
1.異常的基本處理:
(1).當異常被丟擲,其後的程式碼不會繼續執行,php嘗試查詢匹配的catch程式碼塊;見案例1.
(2).如果異常沒有被捕獲,而且有沒有使用set_exception_handler()做相應的處理,那麼會發生一個嚴重的錯誤(致命錯誤),並輸出"Uncaught Exception"(未捕獲異常)的錯誤訊息;
(3).當catch一個異常,可以進行處理或者不進行處理(在catch函式中,直接丟擲異常,即 throw $e,這時將啟動php系統預設異常處理器(函式)來處理,見案例2。或者自己定義一個頂級異常處理器(函式),見案例3);
通俗理解:即第一次丟擲異常後,使用try{},ctach{}捕獲到第一次丟擲的異常,這時我們如果不對第一次丟擲的異常進行處理,可以將此異常進行第二次丟擲,這時,此異常將交給php預設異常處理器(函式)進行處理,或者交給使用者自己定義的頂級異常處理器(函式)進行處理。
其中,定義頂級異常處理,需要兩個步驟:
步驟一:定義頂級異常處理函式;
步驟二:修改預設定義異常處理函式set_exception_handler("函式名");
案例2:
<?php
function A1($val)
{
if($val=="A")
{
throw new Exception ("不要輸入A");//第一次丟擲異常
}
}
function B1($val)
{
if($val=="B")
{
throw new Exception ("不要輸入B");//第一次丟擲異常
}
}
try
{
A1("A");
}
catch(Exception $e)
{
throw $e; //第二次丟擲異常
/*捕獲異常後,繼續丟擲異常(第二次丟擲異常),這時候將會啟動php預設的異常處理器來處理,
也可以自己定義一個頂級異常處理*/
}
?>
結果:
Fatal error: Uncaught exception 'Exception' with message '不要輸入A' in E:\Software_default\wamp_wwwroot\exception\exception02.php:6 Stack trace: #0 E:\Software_default\wamp_wwwroot\exception\exception02.php(18): A1('A') #1 {main} thrown in E:\Software_default\wamp_wwwroot\exception\exception02.phpon line 6
案例3:
<?php
function MyException($e)//使用者定義的頂級異常處理函式
{
echo "<b>我是頂級異常處理函式,</b>其中,異常資訊為:".$e->getMessage();
}
set_exception_handler("MyException");//修改預設的頂級異常處理函式
function A1($val)
{
if($val=="A")
throw new Exception ("不要輸入A");//丟擲異常
}
function B1($val)
{
if($val=="B")
throw new Exception ("不要輸入B");
}
try
{
A1("A");
}
catch(Exception $e)
{
throw $e;
/*繼續丟擲異常,這時候將會啟動php預設的異常處理器來處理,
也可以自己定義一個頂級異常處理*/
}
?>
結果:
我是頂級異常處理函式,其中,異常資訊為:不要輸入A
(4).如果丟擲一個異常,就必須捕獲它(否則會報錯,產生Fatal error錯誤),或者使用使用者定義的頂級異常處理函式進行處理
2.也可以自己定義一個異常類
class MyException Exception
{
}
3.使用多個catch程式碼塊可以捕獲不同種類的異常
(1).基本用法
try
{
//程式碼
//可能丟擲多種異常
}
catch(PDOException $e)//資料庫異常
{
//程式碼
}
catch(Exception $e)
{
//程式碼
}
(2).案例
案例4:
<?php
//定義一個異常類
class MyException1 extends Exception{
}
class MyException2 extends Exception{
}
function A()
{
throw new MyException1("a");
}
function B()
{
throw new MyException1("b");
}
function C()
{
try{
A();//丟擲MyException1
B();//丟擲MyException2
}
catch(Exception1 $e1){
echo $e1->getMessage();
}
catch(Exception2 $e2){
echo $e2>getMessage();
}
}
C();
?>
結果:
Fatal error: Uncaught exception 'MyException1' with message 'a' in E:\Software_default\wamp_wwwroot\exception\exception04.php:12 Stack trace: #0 E:\Software_default\wamp_wwwroot\exception\exception04.php(21): A() #1 E:\Software_default\wamp_wwwroot\exception\exception04.php(31): C() #2 {main} thrown in E:\Software_default\wamp_wwwroot\exception\exception04.phpon line 12
由於產生不捕獲的異常,php預設顯示其異常處理函式,這時,我們新增使用者自定義的頂級處理函式
案例5:
<?php
//定義一個異常類
class MyException1 extends Exception{
}
class MyException2 extends Exception{
}
function MyException($e)
{
echo "<b>我是頂級異常處理函式,</b>其中,異常資訊為:".$e->getMessage();
}
set_exception_handler("MyException");//修改預設的頂級異常處理函式
function A()
{
throw new MyException1("a");
}
function B()
{
throw new MyException1("b");
}
function C()
{
try{
A();//丟擲MyException1
B();//丟擲MyException2
}
catch(Exception1 $e1){//Exception1 是異常類名
echo $e1->getMessage();
}
catch(Exception2 $e2){//Exception2是異常類名
echo $e2>getMessage();
}
}
C();
?>
結果:
我是頂級異常處理函式,其中,異常資訊為:a
3.PHP異常丟擲的BUG
案例6:
<?php
try{
$a=8/0;
}
catch(Exception $e){
echo
$e->getMessage();
echo "異常";
}
?>
結果:
Warning: Division by zero in E:\Software_default\wamp_wwwroot\exception\exception06.phpon line 3
在案例6中,8/0,php認為是錯誤,而不是異常,所以,沒有丟擲異常,因此捕獲不到異常
案例7:
<?php
try{
$f=fopen("aa.txt","r");//aa.txt在當前路徑下並不存在
}
catch(Exception $e){
echo
$e->getMessage();
echo "異常";
}
?>
結果:
Warning: fopen(aa.txt) [function.fopen]: failed to open stream: No such file or directory in E:\Software_default\wamp_wwwroot\exception\exception07.phpon line 3
在案例7中, fopen()是一個很老的函式,從php1就已經存在了,當時並沒有異常處理機制,php認為是錯誤,而不是異常,所以,沒有丟擲異常,因此捕獲不到異常
附:原始碼下載:http://download.csdn.net/detail/wmin510/9528266