若是你调一个类,调用时数据验证时报了个错,你会以什么方式返回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) { // 这里取得的异常只会是继承这个接口的异常 // 能够只针对这个工具包进行处理 }