1. 程式人生 > >詳細解讀php的異常處理機制

詳細解讀php的異常處理機制

異常機制

.異常基本知識

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!修改失敗

.異常使用的注意事項

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/0php認為是錯誤,而不是異常,所以,沒有丟擲異常,因此捕獲不到異常

案例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