許多程序已經使用了PEAR的包。許多php(做為現在的主流開發語言)程序員或多或少的熟悉了PEAR中的錯誤處理。但是這個機制並不局限於PEAR的包——所有人都能在他們的類和程序中使用這些方法。
這篇文章被分為兩個部分:首先我們將看看類中用於錯誤處理的函數,然後我們將看看如何基於PEAR錯誤處理機制來處理錯誤。
我們的例子類稱為cvs2db,它把數據從CSV文件插入到數據庫的表中。因為數據可能是手寫的,他們的數據應該在插入之前先得到驗證——落實postcode。函數import()完成讀入,檢查和插入的工作;它返回損壞的記錄數目。如果返回的值大於0,出錯的記錄集能夠使用exportUnvalid()寫入到新的CSV文件中。典型的用法是這樣的:
(做為現在的主流開發語言)
$cd = new csv2db();
$dsn = MySQL(和PHP搭配之最佳組合)://root@localhost/csv2db;
if( 0 < $cd->import("./dat.csv", $dsn, address)) {
$cd->exportUnvalid("./dat2.csv");
}
?>
可能的錯誤包括:
要導入的CSV文件不存在,
連接到數據庫失敗,
記錄集損壞,以及CSV導出文件無法創建。
在提供錯誤信息的經典解決方案中你可能寫這樣的代碼:
(做為現在的主流開發語言)
$cd = new csv2db();
$dsn = MySQL(和PHP搭配之最佳組合)://root@localhost/csv2db;
$result = $cd->import("./dat.csv", $dsn, address)
switch($result) {
case FILE_NOT_OPENED:
...
break;
case DATABASE_ERROR:
...
break;
default:
if(0 < $result) {
$cd->exportUnvalid("./dat2.csv");
} else {
echo every thing ok!
}
}
?>
這對於短的腳本來說是可接受的也是常用的辦法——但是對於錯誤處理經常受到關注的大程序來說不是這樣。傳統的可能性強迫類的作者做最終的決定!在大部分情況下,這個決定根據的是那時對類的調用而不是基於長期的使用和可重用代碼的思想。一個靈活的錯誤處理機制是可重用代碼的重要部分,PEAR Error API 就是這樣的一種受到良好測試的機制。
用戶眼中的類
除了那兩個函數之外,類提供了一套錯誤處理函數和一個自己的錯誤對象稱為DB2CVS_Error,它有一個特殊的本地化的錯誤信息的特性功能。
現在我將向你展示如何在錯誤發生時控制類的行為。
局部和全局錯誤處理
你用setErrorHandling()管理錯誤處理;這個函數需要兩個參數:第一個是錯誤模式,而第二個(可選的)參數是錯誤模式特定的選項。例如 setErrorHandling(PEAR_ERROR_PRINT, This error occurred %s) 還有 setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING)。
這個函數的調用方式是一般行為中最重要的:靜態還是實體。在類cvs2db中,我們能兩者都用來設置錯誤處理,所有這些調用有相同的結構——為類設置錯誤模式:
// per instance
$cd = new csv2db();
$cd->setErrorHandling(PEAR_ERROR_DIE):
// static
CVS2DB::setErrorHandling(PEAR_ERROR_DIE);
PEAR::setErrorHandling(PEAR_ERROR_DIE);
如果兩者給出同樣的結果,區別在哪?實體調用僅僅為那個類設置而靜態調用對於所有使用PEAR_Error或者從那個類派生的所有類起作用。這個也作用於第一個靜態命令CVS2DB::setErrorHandling(PEAR_ERROR_DIE)——雖然它看上去僅僅影響了cvs2db類。
總結:作為一個實體函數使用命令意味著僅僅為這個實體(局部)設置錯誤模式,而作為靜態函數來調用就是為整個腳本設置錯誤模式(全局)。
setErrorHandling() 和 raiseError()
兩個函數都能夠被靜態調用和作為實體的函數調用。記住怎樣的一個組合使得他們如何互相影響的很重要。
基本上是:setErrorHandling()的靜態調用僅僅影響raiseError()的靜態調用——setErrorHandling()作為實體函數僅僅影響raiseError()作為靜態函數調用。在類csv2db中,使用csv2db::setErrorHandling()來設置錯誤模式是不可行的,因為我們使用$this->raiseError(...)。解決這個聞天有一點小技巧——改寫raiseError():