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