首頁 > 後端開發 > php教程 > PHP主|例外

PHP主|例外

尊渡假赌尊渡假赌尊渡假赌
發布: 2025-02-25 08:30:09
原創
538 人瀏覽過

PHP Master | Exceptional Exceptions

核心要點

  • PHP 異常是一種特殊的類,可以拋出和捕獲,表示意外事件。與不可恢復的錯誤不同,異常旨在由調用代碼處理,並沿執行鏈向上冒泡,直到被捕獲。
  • PHP 錯誤和異常的區別在於:錯誤是不可恢復的,發生在主執行循環中,表示代碼或環境穩定性存在問題;而異常是可恢復的,可能發生在主執行循環之外,並且不表示系統不穩定。
  • 不是所有非成功的情況都需要拋出異常。只有在確實無法繼續執行時才應拋出異常。這意味著一個不屬於普通操作或標準的動作,一個異常,與正常和預期情況有所偏差。
  • 拋出一般的 Exception 等同於說存在“問題”,而代碼無法知道發生了什麼。相反,應始終拋出自定義異常,以告知調用代碼當前情況,從而對發生的情況進行細粒度控制。
  • 全局捕獲塊是最高級別的捕獲塊,必須捕獲所有冒泡到該級別的異常。它應該是生產代碼中唯一的一般異常處理程序。其他處理程序必須是特定的,並且僅限於它知道如何處理和負責的異常。

PHP 5 引入了異常處理機制,這是一種特殊的類,可以拋出和捕獲(與引發的錯誤相反),表示意外事件。與錯誤不同,異常旨在由調用代碼處理,並沿執行鏈向上冒泡,直到被捕獲。一旦拋出異常,當前作用域中的代碼將停止執行(因此,throw 語句之後的任何行都不會執行),控制權將返回到第一個匹配的異常處理程序(捕獲塊、配置的異常處理程序或語言提供的異常處理程序)。只有當異常被捕獲時,代碼執行才會從那裡繼續。本文並非旨在從入門級別講解異常,而是就如何更好地使用異常提供一些建議。如果您以前從未使用過異常,您可能需要查閱PHP 手冊,或閱讀我的朋友們編寫的《PHP Master:編寫尖端代碼》一書,該書出色地講解了編寫現代、合理的PHP 代碼所需的一切知識。

錯誤並非異常

您可能已經了解了異常,但您可能想知道 PHP 錯誤和(自定義)異常之間的區別。邏輯實際上很簡單:錯誤是不可恢復的,發生在主執行循環中,並且表示環境的穩定性。例如,如果您嘗試將標量值作為數組訪問而引發了 E_NOTICE,則表示您的代碼存在問題。無法保證繼續執行是安全的。無法在執行期間糾正該條件。如果由於解析器發現意外的 T_IF 而引發了 E_PARSE,那麼您就會明白這如何影響事物的穩定性。另一方面,異常是可恢復的,可以(並且通常會)發生在主執行循環之外,並且不會指示系統的穩定性。它是一個組件說:“我無法使用給定的輸入完成您的請求,因此您可以隨意處理該信息。”如果庫拋出LengthException,則表示傳遞的值過長或過短,因此它無法使用當前值完成給定的指令。這並不意味著您的環境不穩定,只是意味著您的代碼必須通過填充或截斷來調整值的長度。您的代碼可以捕獲此異常,更新值,然後重試。

並非所有異常都是例外情況

這是最難回答的問題之一:究竟什麼情況需要拋出異常?當然,您的異常必須符合上一段中的三個規則。當遇到損壞的內存時拋出異常是非常糟糕的做法。您的代碼應該改為引發錯誤,以便 PHP 能夠盡快中止,因為事實證明,環境不安全以繼續執行。但是,即使錯誤是不必要的,也不是所有非成功的情況都需要異常。也就是說:並非所有不成功的情況都是例外情況。 “異常”這個詞指的是不屬於普通操作或標準的動作,一個異常,與正常和預期情況有所偏差。一位前同事曾經在晚餐時告訴我他們公司使用的 XML/RPC 服務的設計情況,該服務是所有面向公眾的操作的支柱。架構師隨後了解了異常以及它們在指示非成功狀態方面的便利性。該支柱除了其他功能外,還提供了單點登錄功能。 Web 應用程序不會直接訪問數據庫,而是查詢 XML/RPC 服務,然後該服務將根據為所有 Web 應用程序提供服務的集中式數據存儲進行回复。當提供有效的憑據時,將返回成功狀態。當出現問題時,將拋出異常,並顯示一條消息,指示失敗的原因。易於捕獲,您可以以醒目的、閃亮的錯誤消息向用戶顯示該消息。但是,用戶提供不正確的用戶名和/或密碼真的偏離了預期嗎?在我的項目中,我處理的用戶並不完美,他們會打錯字或忘記事情。獲取不正確的憑據是非常常見的,甚至比有效的憑據更常見。驗證憑據是登錄系統的預期行為,因此在這種情況下,XML/RPC 服務應返回一個狀態,指示驗證的成功與否。儘管憑據未通過,但驗證過程本身仍然成功執行。如果驗證過程未正確執行,則說明還有其他問題。也許數據存儲不可訪問,或者其他什麼原因。登錄系統無法連接到其數據存儲的情況非常不常見,因為它無法在沒有數據存儲的情況下運行。因此,這需要拋出異常。注意:有些人可能會爭辯說,登錄系統無法連接到數據存儲是環境不穩定的標誌,因此應該引發錯誤。但是,登錄系統不負責為數據存儲引發錯誤。相反,如果數據存儲連接器/包裝器認為有必要,則應引發錯誤。一般來說,您可以將異常視為開發人員必須介入、查看情況並進行處理的情況。發生異常場景的代碼本身無法做到這一點。這可能是開發人員已經查看過代碼,並且他們處理它的方式是在它發生時讓它發生。不要開始將所有異常都通過郵件發送給網絡運營中心;他們不會感激的!處理您可以並且應該處理的內容,並且只有在確實無法繼續執行時才拋出異常。

“問題”

幾年前,當我徒步旅行穿過歐洲時,我在希臘的一個火車站偶然發現了一個令人難忘的景象。其中一個儲物櫃區域看起來像炸彈爆炸了一樣,門散落在地上,一半掛在鉸鏈上,或者被砸碎了。我後來了解到他們正在拆除儲物櫃區域,但值得注意的是,他們是如何向客戶傳達此區域已停用的。在中央部分貼了很多膠帶,上面貼著一張紙,上面寫著“問題”兩個字。從技術上講,這是完全正確的。儲物櫃顯然出了問題,並且情況已通過向客戶傳達來處理。您可能會覺得它很有趣,但實際上您在代碼中經常會看到這種情況。如果您只拋出 Exception,那麼您基本上就是在說“問題”,而代碼無法知道發生了什麼。雖然 Exception 是每個異常的基類,但您可以使用您自己的類型擴展它。在 SPL 庫中可以找到更廣泛的異常集合,但這遠非極限。查看 Zend Framework 或 Symfony 等主要的 PHP 框架,您會發現它們幾乎為每種不同的情況都使用自定義異常。編寫所有這些文件以便可以動態加載它們並維護所有不同類型有點麻煩,但這為框架和該框架的使用者提供了對發生情況的細粒度控制。如果只拋出 Exception,那麼您只能確定某些事情不對勁,您不妨放棄。這意味著您使用異常的方式就像它們是錯誤一樣,將捕獲塊用作靜默操作符,並且只是放棄了有人可以以某種方式糾正這種情況的希望。

全局捕獲

如果使用非自定義異常和捕獲所有可能的異常是一個壞主意,那麼為什麼語言甚至允許這樣做呢?始終使用和捕獲特定異常的規則有一個例外,那就是全局捕獲規則。全局捕獲塊是最高級別的捕獲塊,必須捕獲所有冒泡到該級別的異常。 PHP 本身包含一個(您是否見過“致命錯誤:未捕獲的異常在……”消息?),但您可以使用自定義處理程序覆蓋它以作為後備。您可以使用 set_exception_handler() 函數設置此處理程序,因此您可以隨意這樣做,然後向您的 PHPMD 規則集中添加一條規則,禁止類似於“catch (Exception $e) {”之類的行。這是唯一一個應該在生產代碼中找到的一般異常處理程序的原因,它捕獲尚未捕獲的 Exception 類的每個實例。其他處理程序必須是特定的,並且僅限於它知道如何處理和負責的異常。在這裡謹慎行事,讓一個可處理的異常冒泡一次(然後在代碼中修復它)肯定比捕獲太多並充當靜默操作符要好得多。

總結

總而言之,只有當您的代碼無法使用給定的輸入完成請求的指令時才拋出異常,始終拋出自定義異常,該異常實際上會告訴調用代碼當前情況,並且如果您調用其他代碼,則只捕獲您可以並且應該處理的異常。這將使您的組件更少像黑盒(自定義異常),並減少集成您的組件的開發人員必須更改您的代碼的可能性(不要捕獲您不應該捕獲的異常)。我們總是告訴我們的客戶/管理人員要具體,但我們也應該具體!

(圖片來自 Fotolia)

關於 PHP 異常處理的常見問題

  • PHP 異常處理的目的是什麼?

PHP 異常處理是一種強大的機制,允許開發人員管理程序執行期間可能發生的錯誤和異常情況。它提供了一種將控制從程序的一個部分轉移到另一個部分的方法。 PHP 異常處理用於在發生指定錯誤時更改代碼執行的正常流程。這可以使代碼更易於閱讀和管理,因為它將錯誤處理代碼與主程序邏輯分開。

  • PHP 中的 try-catch 塊是如何工作的?

在 PHP 中,try-catch 塊用於處理異常。 try 塊包含可能拋出異常的代碼,而 catch 塊包含如果 try 塊中拋出異常將執行的代碼。如果 try 塊中拋出異常,則腳本停止運行,控制權將傳遞給與拋出的異常類型匹配的第一個 catch 塊。

  • finally 塊在 PHP 異常處理中的作用是什麼?

PHP 異常處理中的 finally 塊用於確保始終執行一段代碼,無論是否拋出異常。這對於清理活動(例如關閉文件或數據庫連接)非常有用,無論操作成功還是失敗都應執行這些活動。

  • 如何在 PHP 中創建自定義異常?

在 PHP 中,您可以通過擴展內置的 Exception 類來創建自定義異常。這允許您向異常添加自定義功能,或創建特定於應用程序域的異常。要創建自定義異常,您可以定義一個擴展 Exception 的新類,然後添加所需的任何自定義方法或屬性。

  • PHP 中異常和錯誤有什麼區別?

在 PHP 中,錯誤是一個嚴重的問題,會阻止腳本運行,而異常是一個改變正常執行流程的條件。錯誤通常是由語法錯誤或調用未定義函數等原因引起的。另一方面,異常通常用於處理對程序並非致命但需要特殊處理的條件。

  • 如何在 PHP 中處理多個異常?

在 PHP 中,您可以使用多個 catch 塊來處理多個異常。每個 catch 塊處理特定類型的異常。當拋出異常時,將按代碼中出現的順序檢查 catch 塊。將執行第一個能夠處理拋出的異常類型的 catch 塊。

  • 我可以在 PHP 中重新拋出異常嗎?

是的,您可以在 PHP 中重新拋出異常。如果您想以某種方式處理異常,但又想讓更高級別的異常處理程序捕獲它,這將非常有用。要重新拋出異常,只需在 catch 塊中使用 throw 語句即可。

  • 如何在 PHP 中記錄異常?

在 PHP 中,您可以通過在 catch 塊中使用 error_log 函數來記錄異常。這允許您將有關異常的信息(包括其消息和堆棧跟踪)記錄到指定的日誌文件中。

  • PHP 中的 PDOException 是什麼?

PDOException 是一種異常,當 PDO 操作中發生錯誤時會拋出該異常。 PDO(PHP 數據對象)是一個數據庫抽象層,它為訪問 PHP 中的數據庫提供一致的接口。 PDOException 提供有關錯誤的信息,包括 SQLSTATE 錯誤代碼和數據庫驅動程序的錯誤消息。

  • 如何在 PHP 中處理未捕獲的異常?

在 PHP 中,您可以通過定義自定義異常處理程序函數,然後使用 set_exception_handler 函數將其設置為默認異常處理程序來處理未捕獲的異常。每當拋出未被 try-catch 塊捕獲的異常時,都會調用此函數。

以上是PHP主|例外的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板