若是你調一個類,調用時數據驗證時報了個錯,你會以什麼方式返回php
數組,布爾值?git
數組這個能夠帶錯誤緣由回來,那布爾值呢?github
返回了個 false, 報錯時把錯誤放在類變量裏?
仍是專門用一個獲取錯誤的方法進行獲取?sql
上面說的狀況是代碼徹底沒有問題的狀況。
那若是是一些第三方的工具包,你又怎麼知道他裏面的執行會不會致使整個系統崩潰。數組
你說本地運行是沒問題的,環境這種東西很差說。composer
因此咱們就用到了 異常 這個東西函數
下面是咱們須要瞭解的問題工具
何時拋異常?怎麼接異常?異常要怎麼處理?他的使用場景又是什麼?this
try ... catch()
throwspa
致命錯誤 E_ERROR,
語法錯誤 E_PARSE,
警告錯誤 E_WARNING,
通知錯誤 E_NOTICE
* ErrorException (extends Exception)
* LogicException (extends Exception) // 表示程序邏輯中的錯誤的異常。這種異常應該直接在代碼中的修復 * BadFunctionCallException // 回調調用未定義的函數或缺乏一些參數時會拋出該異常 * BadMethodCallException // 回調方法是一個未定義的方法或缺失一些參數時會拋出該異常 * DomainException // 值不遵照定義的有效數據域時會拋出該異常 * InvalidArgumentException // 參數不是預期類型時會拋出該異常 * LengthException // 長度無效時會拋出該異常 * OutOfRangeException // 請求非法索引時引起的異常,這應該在編譯時就檢測到的錯誤 * RuntimeException (extends Exception) // 在運行時發生的錯誤會拋出該異常 * OutOfBoundsException // 值不是有效鍵時會拋出該異常,這表示在編譯時沒法檢測到的錯誤 * OverflowException // 在向完整容器中添加元素時引起的異常 * RangeException // 在程序執行期間爲指示範圍錯誤而引起的異常。一般這意味着除了/overflow之外還有一個算術錯誤。這是運行時的DomainException版本 * UnderflowException // 在空容器上執行無效操做(如刪除元素)時引起的異常 * UnexpectedValueException // 值與一組值不匹配時會拋出該異常。一般,當一個函數調用另外一個函數並指望返回值爲某種類型或值(不包括算術或緩衝區相關錯誤)時,就會發生這種狀況
error_reporting // 設置報告的錯誤級別 register_shutdown_function // 註冊一個會在php停止時執行的函數 set_error_handler // 設置用戶自定義的錯誤處理函數 set_exception_handler // 設置用戶自定義的異常處理函數 error_get_last // 獲取最後發生的錯誤
主要抓的是沒法預測的錯誤,統一返回,沒有使用 try...catch 接收的異常直接跳進設置的方法中
<?php namespace App\Exception; use Exception; /** * 異常句柄(入口)類 */ class Handler { // 默認錯誤處理 public static function errorHandler($errno, $errstr, $errfile = '', $errline = 0) { } // 默認異常處理 public static function exceptionHandler($ex) { try { throw $ex; } catch (Order $e) { echo "訂單異常"; } catch (Goods $e) { echo "商品異常"; } catch (User $e) { echo "用戶異常"; } catch (Exception $e) { echo "其餘異常"; } } // 致命錯誤處理 public static function fatalErrorHandler() { if ($e = error_get_last()) { print_r($e); } } } /** * 訂單異常 */ class Order extends Exception { } /** * 商品異常 */ class Goods extends Exception { } /** * 用戶異常 */ class User extends Exception { }
<?php // 入口文件中 error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE); register_shutdown_function(array('App\\Exception\\Handler', 'fatalErrorHandler')); set_error_handler(array('App\\Exception\\Handler', 'errorHandler')); set_exception_handler(array('App\\Exception\\Handler', 'exceptionHandler'));
定義自定義的異常,一有錯誤直接拋出。使用工具的程序只需經過 Exception 接收異常便可, 全部異常都經過這個進行處理的
<?php namespace Testlin\Db\Exception; use Exception; interface ExceptionInterface { } class Db extends Exception implements ExceptionInterface { } class Pdo extends Db { } ?> <?php namespace Testlin\Db; use Exception; use Testlin\Db\Exception\Pdo; class Db { protected $db; public function __construct($config) { $this->db = new PDO($config); if ($this->db == false) { throw new Pdo("鏈接失敗"); } } } ?>
一、爲何要定自定義異常類, 系統不是已經給了不少選擇,並且不少 composer 包裏都只是繼承一下。
答:其實自定義異常是爲了用區分異常顆粒度的,好比
我定了 訂單異常,商品異常,用戶異常 類,可是 訂單裏的異常多種多樣,好比訂單支付異常,訂單生成異常。
* RuntimeException (extends Exception) * Order * Paymen * Created * Goods * User * Withdraw
當項目拋出異常時
<?php try { $param = []; // 操做那個方法時傳的參數 throw App\Exception\Order\Payment::forParam('執行xxx操做異常', $param); } catch (Exception $e) { // 相關操做 get_class($e); // 當前異常類 App\Exception\Order\Payment }
經過異常類名,咱們能夠知道是訂單支付異常。這裏能夠代替錯誤號,並且更清晰明瞭
二、爲何有一些 composer 包裏的自定義異常,有的有不少方法。有什麼用處嗎?
做用1:格式化異常
好比:拋出的異常提示是 "id=xx 的用戶不存在",咱們會有如下兩種寫法
<?php // 普通操做 $id = 1; throw new Payment("id={$id} 的用戶不存在"); // 格式化異常 use App\Exception\Order; class Payment extends Order { public static function forId($id) { return new self(sprintf( 'id=%s 的用戶不存在', $id )); } } $id = 1; throw Payment::forId($id);
做用2:組件級別的異常
<?php namespace Testlin\Db\Exception; use Exception; interface ExceptionInterface { } class Mysqli extends Exception impements ExceptionInterface { } class Pdo extends Exception impements ExceptionInterface { } try { throw new Testlin\Db\Exception\Mysqli('sql 執行失敗'); } catch (Testlin\Db\Exception\ExceptionInterface $e) { // 這裏取得的異常只會是繼承這個接口的異常 // 能夠只針對這個工具包進行處理 }