異常機制
一.異常基本知識
1.定義:異常處理用於在指定的錯誤(異常)情況發生時改變腳本的正常流程,這過程稱爲異常.
2.基本用法:
try
{
//可能出現的錯誤(異常)代碼
}
catch(Exception $e)
{
//自己處理:捕捉異常並處理,
//自己不處理:拋出一個異常,即如下:
throw $e;
}
其中,Exception是異常類(php中定義好的一個類,具體參見php參考文檔:語音參考->異常處理).它已經封裝好很多方法,常用如下:
function __construct($message = null, $code = 0);
final function getMessage(); // 返回異常信息
final function getCode(); // 返回異常代碼
final function getFile(); // 返回發生異常的文件名
final function getLine(); // 返回發生異常的代碼行號
final function getTrace(); // backtrace() 數組
final function getTraceAsString(); // 已格成化成字符串的 getTrace() 信息
/* 可重載的方法 */
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!修改失敗
來自 <http://localhost/exception/exception01.php>
二.異常使用的注意事項
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
來自 <http://localhost/exception/exception02.php>
案例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
來自 <http://localhost/exception/exception03.php>
(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
來自 <http://localhost/exception/exception04.php>
由於產生不捕獲的異常,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
來自 <http://localhost/exception/exception05.php>
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
來自 <http://localhost/exception/exception06.php>
在案例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
來自 <http://localhost/exception/exception07.php>
在案例7中, fopen()是一個很老的函數,從php1就已經存在了,當時並沒有異常處理機制,php認爲是錯誤,而不是異常,所以,沒有拋出異常,因此捕獲不到異常
附:源碼下載:http://download.csdn.net/detail/wmin510/9528266