在本教程中,您將學(xué)習(xí)如何在PHP中引發(fā)和捕獲異常。
異常是表示發(fā)生某種異常事件或錯(cuò)誤的信號(hào)??赡苡捎诙喾N原因?qū)е庐惓?,例如,?shù)據(jù)庫(kù)連接或查詢失敗,您嘗試訪問(wèn)的文件不存在等等。
PHP提供了強(qiáng)大的異常處理機(jī)制,使您能夠以優(yōu)美的方式處理異常。與PHP的傳統(tǒng)錯(cuò)誤處理系統(tǒng)相反,異常處理是一種用于處理錯(cuò)誤您可能想知道這段代碼是關(guān)于什么的。好吧,讓我們逐一遍歷此代碼的每個(gè)部分,以更好地理解。
在PHP的異常處理系統(tǒng)有四種基本部分:try,throw,catch,和Exception類。以下列表描述了各個(gè)部分的工作原理。
上例中的division()函數(shù)檢查除數(shù)是否等于零。如果是,則通過(guò)PHP的throw語(yǔ)句拋出異常。否則,此函數(shù)使用給定的數(shù)字執(zhí)行除法并顯示結(jié)果。
然后,在try塊中使用不同的參數(shù)調(diào)用division()函數(shù)。如果在try塊中執(zhí)行代碼時(shí)生成異常,PHP將在該點(diǎn)停止執(zhí)行并嘗試查找相應(yīng)的catch塊。如果找到,則執(zhí)行catch塊中的代碼,否則生成致命錯(cuò)誤。
catch塊通常捕獲try塊中拋出的異常,并創(chuàng)建一個(gè)包含異常信息的對(duì)象($e)??梢允褂卯惓5膅etMessage()方法檢索來(lái)自此對(duì)象的錯(cuò)誤消息。
在PHP的異常類也提供了getCode(),getFile(),getLine()和getTraceAsString()可用于生成詳細(xì)的調(diào)試信息的方法。
<?php
//關(guān)閉默認(rèn)錯(cuò)誤報(bào)告
error_reporting(0);
try{
$file = "somefile.txt";
//嘗試打開(kāi)文件
$handle = fopen($file, "r");
if(!$handle){
throw new Exception("無(wú)法打開(kāi)文件!", 5);
}
//嘗試讀取文件內(nèi)容
$content = fread($handle, filesize($file));
if(!$content){
throw new Exception("Could not read file!", 10);
}
//關(guān)閉文件句柄
fclose($handle);
//顯示文件內(nèi)容
echo $content;
} catch(Exception $e){
echo "<h3>Caught Exception!</h3>";
echo "<p>Error message: " . $e->getMessage() . "</p>";
echo "<p>File: " . $e->getFile() . "</p>";
echo "<p>Line: " . $e->getLine() . "</p>";
echo "<p>Error code: " . $e->getCode() . "</p>";
echo "<p>Trace: " . $e->getTraceAsString() . "</p>";
}
?>異常的構(gòu)造函數(shù)可以選擇接受異常消息和異常代碼。 雖然異常消息通常用于顯示出錯(cuò)原因的一般信息,但異常代碼可用于對(duì)錯(cuò)誤進(jìn)行分類。 稍后可以通過(guò)Exception的getCode()方法檢索提供的異常代碼。
提示:異常僅應(yīng)用于表示特殊情況;它們不應(yīng)用于指定正常的應(yīng)用程序流程,例如,在特定位置跳轉(zhuǎn)到腳本中的其他位置。這樣做會(huì)不利地影響應(yīng)用程序的性能。
您甚至可以定義自己的自定義異常處理程序,以不同的方式處理不同類型的異常。 它允許您為每種異常類型使用單獨(dú)的catch塊。
您可以通過(guò)擴(kuò)展Exception類來(lái)定義自定義異常,因?yàn)镋xception是所有異常的基類。 自定義異常類繼承了PHP Exception類的所有屬性和方法。 您還可以將自定義方法添加到自定義異常類。 讓我們看一下以下示例:
<?php
//擴(kuò)展Exception類
class EmptyEmailException extends Exception {}
class InvalidEmailException extends Exception {}
$email = "someuser@example..com";
try{
//如果電子郵件為空,則拋出異常
if($email == ""){
throw new EmptyEmailException("<p>請(qǐng)輸入您的電子郵件地址!</p>");
}
//如果電子郵件無(wú)效,則拋出異常
if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) {
throw new InvalidEmailException("<p><b>$email</b> 不是有效的電子郵件地址!</p>");
}
// 如果電子郵件有效,則顯示成功消息
echo "<p>成功:電子郵件驗(yàn)證成功.</p>";
} catch(EmptyEmailException $e){
echo $e->getMessage();
} catch(InvalidEmailException $e){
echo $e->getMessage();
}
?>在上面的示例中,我們從Exception基類派生了兩個(gè)新的異常類:EmptyEmailException和InvalidEmailException。 多個(gè)捕獲塊用于顯示不同的錯(cuò)誤消息,具體取決于生成的異常類型。
由于這些自定義異常類繼承了Exception類的屬性和方法,所以我們可以使用異常的類方法,如getMessage(),getLine(),getFile(),等來(lái)檢索異常對(duì)象的錯(cuò)誤信息。
如本章前面所討論的,如果未捕獲到異常,則PHP會(huì)生成一條致命錯(cuò)誤,并帶有“ Uncaught Exception ...”消息。 此錯(cuò)誤消息可能包含敏感信息,例如出現(xiàn)問(wèn)題的文件名和行號(hào)。 如果您不想向用戶公開(kāi)此類信息,則可以創(chuàng)建一個(gè)自定義函數(shù),并向set_exception_handler()函數(shù)注冊(cè)該函數(shù)以處理所有未捕獲的異常。
<?php
function handleUncaughtException($e){
//向用戶顯示一般錯(cuò)誤消息
echo "哎呀!出了點(diǎn)問(wèn)題。請(qǐng)重試,如果問(wèn)題仍然存在,請(qǐng)與我們聯(lián)系。";
// 構(gòu)造錯(cuò)誤字符串
$error = "Uncaught Exception: " . $message = date("Y-m-d H:i:s - ");
$error .= $e->getMessage() . " in file " . $e->getFile() . " on line " . $e->getLine() . "\n";
//在文件中記錄錯(cuò)誤的詳細(xì)信息
error_log($error, 3, "var/log/exceptionLog.log");
}
//注冊(cè)自定義異常處理程序
set_exception_handler("handleUncaughtException");
// 拋出異常
throw new Exception("Testing Exception!");
?>注意:未捕獲的異??偸菚?huì)導(dǎo)致腳本終止。 因此,如果希望腳本在異常發(fā)生點(diǎn)之后繼續(xù)執(zhí)行,則每個(gè)try塊必須至少有一個(gè)對(duì)應(yīng)的catch塊。