如何做好错误处理?(PHP篇)
起因
之前我在封裝 PHP 一個類庫的時候,如果有遇到錯誤(例如構造函數傳參不合法的話),則直接 die() ,后來發現這種方法很不好,會直接退出程序。
所以我想到給 PHP 上異常捕獲的機制了。
錯誤處理的原則
1、一定要讓 PHP 報告錯誤
2、在開發環境中要顯示錯誤
3、在生產環境中不能顯示錯誤
4、在開發和生產環境中都要記錄錯誤
PHP 錯誤處理的種類
一、@
盡管我們可以在可能觸發錯誤的函數前加上 @ 抑制符,不讓 PHP 觸發錯誤,但這有悖于常規做法,不建議這么做。
二、die()
因為 die() = exit() ,遇到錯誤直接退出,很不友好。
但是早期的一些 PHP 框架和類庫還在使用這種方法,例如 codeigniter。
三、Error
(1) 實例:
//錯誤處理函數 function MyError($level, $message, $file = '', $line = 0, $context = []) {//todo... } //設置錯誤處理函數 set_error_handler("MyError", E_ALL & ~E_NOTICE); //排除了 E_NOTICE,攔截沒有必要的錯誤提示// 觸發錯誤 $test=2; if ($test>1) {trigger_error("變量值必須小于等于 1",E_USER_WARNING); }//恢復錯誤處理設置(可選) //restore_error_handler()(2) 錯誤處理函數 的參數(對應例子中的 MyError())
| error_level | 必需。為用戶定義的錯誤規定錯誤報告級別。必須是一個數字。參見下面的表格:錯誤報告級別。 |
| error_message | 必需。為用戶定義的錯誤規定錯誤消息。 |
| error_file | 可選。規定錯誤發生的文件名。 |
| error_line | 可選。規定錯誤發生的行號。 |
| error_context | 可選。規定一個數組,包含了當錯誤發生時在用的每個變量以及它們的值。 |
(3) error_level (錯誤報告的級別)
| 2 | E_WARNING |
| 8 | E_NOTICE |
| 256 | E_USER_ERROR |
| 512 | E_USER_WARNING |
| 1024 | E_USER_NOTIC |
| 4096 | E_RECOVERABLE_ERROR |
| 8191 | E_ALL |
四、Exception
早期的 PHP 只有錯誤沒有異常。
現在的一些 PHP 框架和類庫已經離不開異常了,例如laravel。
(1)Exception 對象
參數: Code + Message
$exception = new Exception('Danger, Will Robinson!', 100);$code = $exception->getCode(); $message = $exception->getMessage();(2) 實例
ini_set('display_errors', 'Off'); // 隱藏所有錯誤的顯示 error_reporting(E_ALL & ~E_NOTICE); //將會向 PHP 報告發生的每個錯誤,除了 E_NOTICE ini_set("log_errors", 'On'); //開啟錯誤日志??? ini_set('error_log', dirname(__FILE__) . '/../php_errors.log'); //指定產生的錯誤報告寫入的日志文件位置??// ********** 異常 **********//自定義 Exception class CustomException extends Exception {public function errorMessage(){// 自定義錯誤信息$errorMsg = '錯誤行號 '.$this->getLine().' in '.$this->getFile().': <b>'.$this->getMessage().'</b>';return $errorMsg;} } //設置頂層異常處理器 set_exception_handler(function (Exception $e) {$exception_name = get_class($e);if ($exception_name === "InvalidArgumentException") { //PHP 內置 Exception//todo...} else if ($exception_name === "CustomException") { //自定義 Exception//todo...} else {//todo...} });//觸發異常 throw new MyException('x','xxx'); throw new Exception('Uncaught Exception occurred');//還原成之前的全局異常處理程序 //restore_exception_handler();(3) PHP 內置的 Exception 對象
| Error | |
| ArithmeticError | 計算錯誤 |
| DivisionByZeroError | 不可以除以0的錯誤 |
| AssertionError | 斷言錯誤 |
| ParseError | parse錯誤 |
| TypeError | 類型錯誤 |
| ArgumentCountError | 參數數量錯誤 |
| Exception | |
| ClosedGeneratorException | 當生成器的值已經用完時,請求新的值將觸發此異常。 |
| DOMException | |
| ErrorException | |
| IntlException | Internationalization(國際化)錯誤 |
| LogicException | 邏輯錯誤 |
| BadFunctionCallException | 如果回調引用未定義的函數或缺少某些參數,則拋出異常。 |
| BadMethodCallException | 當一個回調方法是一個未定義的方法或缺失一些參數時會拋出該異常。 |
| DomainException | 如果值不符合已定義的有效數據域,則拋出異常。 |
| InvalidArgumentException | 無效參數錯誤 |
| LengthException | 長度錯誤 |
| OutOfRangeException | 越界錯誤 |
| PharException | Phar類錯誤 |
| ReflectionException | |
| RuntimeException | 如果只能在運行時發現錯誤,則拋出異常。 |
| OutOfBoundsException | 如果值不是有效的鍵,則拋出異常。 |
| OverflowException | 溢出錯誤 |
| UnderflowException | 下溢錯誤。在空容器上執行無效操作(例如移除元素)時拋出異常。 |
| PDOException | POD類錯誤 |
| RangeException | 范圍錯誤 |
| UnexpectedValueException | 不期望的參數值錯誤 |
| SodiumException? | Sodium類錯誤 |

總結:
錯誤 和 異常 的區別:
(1) 觸發方式不同
Error
trigger_error(錯誤級別)Exception
throw(new xxxException)(2) 目的不同
error 單純是報錯,而 exception 的目的是為了被捕獲,從而補救錯誤。
? ? ? ?
對于高版本 PHP 我們基本上只需要處理異常,不用管錯誤,或者用全局接管錯誤,然后再拋為異常。
(3) PHP 錯誤機制圖解

參考資料
[1] http://www.cnblogs.com/yjf512/p/5314345.html(PHP 的錯誤機制總結)
[2] https://juejin.im/entry/5987d2ff6fb9a03c314fe732(PHP 的錯誤和異常處理機制)
[3] http://laravelacademy.org/post/7500.html (最佳實踐系列(十一):深入探討 PHP 錯誤異常處理機制及 Laravel 框架底層的相應實現)
[4] http://php.net/manual/en/class.error.php (PHP Manual?Language Reference?Predefined Exceptions)
? ? ? ?
[5] http://www.runoob.com/php/php-exception.html (PHP 異常處理)
[6] http://www.runoob.com/php/php-error.html (PHP 錯誤處理)
轉載于:https://www.cnblogs.com/xjnotxj/p/9231297.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的如何做好错误处理?(PHP篇)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 能力培养与测试八年级下册英语电子版
- 下一篇: 不会英语可以学习编程专业嘛?