1.Exception類php
這個類是PHP爲異常處理提供的內置類。構造函數的兩個參數分別是錯誤消息和錯誤代碼。html
除了構造函數以外,該類還提供了以下的內置方法:web
· getCode() 返回傳遞給構造函數的代碼數據庫
· getMessage() 返回傳遞給構造函數的消息數組
· getFile() 返回產生異常的代碼文件的完整路徑app
· getLine() 返回代碼文件中產生異常的代碼行號函數
· getTrace() 返回一個包含了產生異常的代碼回退路徑的數組ui
· getTraceAsString() 返回與getTrace()方向相同的信息,該信息將被格式化成一個字符串。this
· _toString() 容許簡單地顯示一個Exception對象,而且給出以上全部方法能夠提供的信息。編碼
經過執行如下命令,能夠得到相同的異常信息(以及代碼回退路徑):
echo $e;
回退路徑顯示了在發生異常時所執行的函數。
2.異常控制結構
異常處理的基本思想是代碼在try代碼塊被調用執行。在PHP中,異常必須手動拋出。
異常控制結構:try...throw...catch
能夠將多個catch代碼塊與一個try代碼塊進行關聯。還能夠在一個catch代碼塊產生新的異常。
以下代碼拋出並捕獲一個異常:
<?php try { throw new Exception("A terrible error has occurred", 42); } catch (Exception $e) { echo "Exception ". $e->getCode(). ": ". $e->getMessage()."<br />". " in ". $e->getFile(). " on line ". $e->getLine(). "<br />"; } ?>
這裏咱們使用了exception類的前四個方法,catch代碼塊報告了異常錯誤信息以及發生錯誤位置的說明。
3.用戶自定義異常
能夠擴展Exception類來建立本身的異常類。
可能須要繼承的代碼:
<?php class Exception{ function __construct(string $message=NULL,int $code=0){ if(func_num_args()){ $this->message = $message; } $this->code = $code; $this->file = __FILE__; // of throw clause $this->line = __LINE__; // of throw clause $this->trace = debug_backtrace(); $this->string = StringFormat($this); } protected $message = "Unknown exception "; // exception message protected $code = 0; // user defined exception code protected $file; // source filename of exception protected $line; // source line of exception private $trace; // backtrace of exception private $string; // internal only!! final function getMessage(){ return $this->message; } final function getCode(){ return $this->code; } final function getFile(){ return $this->file; } final function getTrace(){ return $this->trace; } final function getTraceAsString(){ return self::TraceFormat($this); } function _toString(){ return $this->string; } static private function StringFormat(Exception $exception){ // ... a function not available in PHP scripts // that returns all relevant information as a string } static private function TraceFormat(Exception $exception){ // ... a function not available in PHP scripts // that returns the backtrace as a string } } ?>
該類的大多數公有方法都是final的:這就意味着不能重載這些方法。咱們能夠建立本身的Exception子類,可是不能改變這些基本方法的行爲。請注意,_toString()函數能夠重載,所以咱們能夠改變異常的顯示方式。也能夠添加本身的方法。
用戶自定義的Exception類示例:
<?php class myException extends Exception { function __toString() { return "<table border=\"1\"> <tr> <td><strong>Exception ".$this->getCode()." </strong>: ".$this->getMessage()."<br />"." in ".$this->getFile()." on line ".$this->getLine()." </td> </tr> </table><br />"; } } try { throw new myException("A terrible error has occurred", 42); } catch (myException $m) { echo $m; } ?>
在以上代碼中,咱們聲明瞭一個新的異常類myException,該類擴展了Exception基類。該類與Exception類之間的差別在於重載了_toString()方法,從而爲打印異常提供了一個更好的方法。
4.文件I/O相關的異常
寫文件時可能會出現三種狀況的錯誤:文件沒法打開、沒法得到寫鎖或者文件沒法寫入。咱們爲每一種可能性都建立了一個異常類:
<?php class fileOpenException extends Exception { function __toString() { return "fileOpenException ". $this->getCode() . ": ". $this->getMessage()."<br />"." in " . $this->getFile(). " on line ". $this->getLine() . "<br />"; } } class fileWriteException extends Exception { function __toString() { return "fileWriteException ". $this->getCode() . ": ". $this->getMessage()."<br />"." in " . $this->getFile(). " on line ". $this->getLine() . "<br />"; } } class fileLockException extends Exception { function __toString() { return "fileLockException ". $this->getCode() . ": ". $this->getMessage()."<br />"." in " . $this->getFile(). " on line ". $this->getLine() . "<br />"; } } ?>
Exception類的這些子類並無執行任何特別的操做。事實上,對於這個應用程序的做用來講,可讓它們成爲空的子類或者使用PHP所提供的Exception類。然而,咱們爲每一個子類提供了_toString()方法,從而能夠解釋所發生的異常類型:
<?php require_once("file_exceptions.php"); // create short variable names $tireqty = $_POST['tireqty']; $oilqty = $_POST['oilqty']; $sparkqty = $_POST['sparkqty']; $address = $_POST['address']; $DOCUMENT_ROOT = $_SERVER['DOCUMENT_ROOT']; ?> <html> <head> <title>Bob's Auto Parts - Order Results</title> </head> <body> <h1>Bob's Auto Parts</h1> <h2>Order Results</h2> <?php $date = date('H:i, jS F'); echo "<p>Order processed at ".$date."</p>"; echo '<p>Your order is as follows: </p>'; $totalqty = 0; $totalqty = $tireqty + $oilqty + $sparkqty; echo "Items ordered: ".$totalqty."<br />"; if( $totalqty == 0) { echo "You did not order anything on the previous page!<br />"; } else { if ( $tireqty > 0 ) { echo $tireqty." tires<br />"; } if ( $oilqty > 0 ) { echo $oilqty." bottles of oil<br />"; } if ( $sparkqty > 0 ) { echo $sparkqty." spark plugs<br />"; } } $totalamount = 0.00; define('TIREPRICE', 100); define('OILPRICE', 10); define('SPARKPRICE', 4); $totalamount = $tireqty * TIREPRICE + $oilqty * OILPRICE + $sparkqty * SPARKPRICE; $totalamount=number_format($totalamount, 2, '.', ' '); echo "<p>Total of order is ".$totalamount."</p>"; echo "<p>Address to ship to is ".$address."</p>"; $outputstring = $date."\t".$tireqty." tires \t".$oilqty." oil\t" .$sparkqty." spark plugs\t\$".$totalamount ."\t". $address."\n"; // open file for appending try { if (!($fp = @fopen("$DOCUMENT_ROOT/../orders/orders.txt", 'ab'))) throw new fileOpenException(); if (!flock($fp, LOCK_EX)) throw new fileLockException(); if (!fwrite($fp, $outputstring, strlen($outputstring))) throw new fileWriteException(); flock($fp, LOCK_UN); fclose($fp); echo "<p>Order written.</p>"; } catch (fileOpenException $foe) { echo "<p><strong>Orders file could not be opened. Please contact our webmaster for help.</strong></p>"; } catch (Exception $e) { echo "<p><strong>Your order could not be processed at this time. Please try again later.</strong></p>"; } ?> </body> </html>
能夠看到,以上腳本的文件I/O部分被封裝在一個try代碼塊中。一般,良好的編碼習慣要求try代碼塊的代碼量較少,而且在代碼塊的結束處捕獲相關異常。這使得異常處理代碼更容易編寫和維護,由於能夠看到所處理的內容。
若是沒法打開文件,將拋出一個fileOpenException異常;若是沒法鎖定該文件,將拋出一個fileLockException異常;而若是沒法寫這個文件,將拋出一個fileWriteException異常。
咱們給出了兩個catch代碼塊:一個用來處理fileOpen-Exception異常,而另外一個用來處理Exception。因爲其餘異常都是從Exception繼承過來的,它們將被第二個catch代碼塊捕獲。catch代碼塊與每個instanceof操做符相匹配。這就是爲每個類擴展本身異常類的理由。
若是異常沒有匹配的catch語句塊,PHP將報告一個致命錯誤。
請注意fopen()函數的調用仍然使用了@錯誤抑制操做符前綴。若是該函數調用失敗,PHP將發出一個警告,根據php.ini中的錯誤報告設置不一樣,該警告可能會被報告或者記錄。不管是否產生一個異常,這個警告仍然會發出。
好了,從零開始攻略PHP系列到這裏就水完了,僅供參考,好多我也是隻知其一;不知其二,只是整理出來方便查閱。下個月會陸續發一些數據庫的,也就是該書整理的第二篇。
整理自《PHP and MySQL Web 開發》