针对PHP框架的Exception和Validate的处理

1. Exception处理原因

想必总有过这种状况,你的前端小伙有时收到一个框架自带的报错,一脸懵逼,而后找你,XXXX... 好吧,咱们 PHP 虽然开发敏捷,但也要严谨。...因而乎,查询,嗯,得判空;保存,得判断返回的结果。 哇,发现一个方法里要判断好多好屡次呀,相似下面这种伪代码:(举个例子,实际中可能很少)php

//如下代码写控制器里了

//我要添加一个商品,得先查看该分类是否存在吧
$category = Category::find($category_id);

if (! $category) {
    // 返回自定义错误json给前端...
}

//
$product = Product::create(['name' => 'iphone', ...]);
if (! $product) {
    // 返回自定义错误json给前端...
}

if (isset($product['...'])) {
    // 返回自定义错误json给前端
}
.
.
.
// 对这个才是咱们想要的结果

复制代码

以上放在控制器里自己并没有大碍,可是控制器里,只该呈现大致逻辑代码,查询数据库应写在Model不是么? 是的
Fuck 因而我想了一下该咋办呢 因而有了后面的代码前端

// 模型里的代码
public static function handleProduct() {
    //... 省略
    if (! $category) {
    return 1;
    }
    
    if (! $production) {
        return 2;
    }
    
    if (! $others) {
        return 3;
    }
// .. 后面可能还有
}

复制代码

...laravel

// 控制器里的代码
$result = Product::handleProduct(..);
switch($result) {
    case 1 : 
    // 处理这种状况的报错
    break;
    case 2:
    // 处理第二种状况的报错
    break;
    case 3: 
    // 处理其余状况的报错
    break
}
复制代码

咱们公司不少地方都有这种为了严谨一点,不得不写出这种恶心的代码......数据库

很长一段时间,忽然看到了一种很好很好解决这个问题的办法了... 因而乎,重要关头来了。json

2. 处理异常类

以laravel 框架做为实例,TP5还有其余框架都有的~bash

  • 建立 /app/Exceptions/BaseException.php
namespace App\Exception;

class BaseException extends \Exception {
    /** 自定义http 状态码 * @var int */
    public $code = 400;
    
    /** 自定义错误类型码 * @var int */
    public $errCode = 10000;
    
    /** 自定义错误消息 * @var string */
    public $msg = '';
    
    public function __construct($config = []) {
        if (array_key_exists('code', $config)) {
            $this->code = $config['code']
        }
        
        if (array_key_exists('errCode', $config)) {
            $this->code = $config['errCode']
        }
        
        if (array_key_exists('msg', $config)) {
            $this->code = $config['msg']
        }
    }
}

// 这个类主要用于做为错误基类,主要为了能够在throw new MyException($config),能够自定义错误内容。
复制代码
  • 打开 /app/Exceptions/Handle.php
// 这里关注在render方法,能够重写覆盖render方法

public function render($request, Exception $exception) {
    // 首先咱们得判断 抛出的Exception 是否是继承咱们的基类BaesException
    if ($exception instanceof BaseException) {
        return Response()->json([
            'errCode' => $exception->errCode,
            'msg' => $exception->msg
        ], $exception->code);
    }
    
    // 若是不是咱们想要定义的错误 不在生产环境的话,仍是返回错误页面
    if (env('APP_DEBUG')) {
        parent::render();
    }
    
    // 生产环境
    return Response()->json([
            'errCode' => 999,
            'msg' => '服务器内部错误'
        ], 501);
    
}
复制代码

有了这个,咱们再写代码就舒服啦~ 以下服务器

// 某个模型
public function ManyErrorMethod() {
    if (! $category) {
        throw new CategoryNotFoundException();
    }
    
    if (! $product) {
        throw new SaveDataErrorException(['errCode' => 12001, 'msg' => '保存商品失败'])
    }
}
复制代码

3. 处理验证类

有了以上的异常类,在验证类这一块能够说是很是爽的~app

  • 建立 /app/Validates/BaseValidate.php
class BaseValidate {
    /** 规则 * @var int */
    protected $rule = [];
    
    /** 根据规则返回的错误消息 * @var int */
    protected message = [];
    
    // 以上都是和laravel 自带的 make:request 差很少的。
    
    public functio check($params = [])
    {
        // 若是传了,那么就只验证传过来的参数,不然验证全部参数。
        $params = empty($params) ? request()->all() : $params;
        
        $validate = Validator::make($param, $this->rule);
        
        // 若是验证没经过
        if ($validate->fails()) {
            // 抛出自定义的异常,记得继承上面说的 BaseException
            throw new CustomException([
                'code' => '400',
                'errCode' => $validate->messages()->first()
            ]);
        }
        return;
    }
    
    // 差很少就这样完成了,不过有个问题,就是不一样的参数错误,应该对应不一样的错误码。
    // 因此,能够更改一下上面 错误类的 render 方法
}
复制代码
  • 更改 /app/Exception/Handle.php
public function render($request, Exception $exception) {
         // 首先咱们得判断 抛出的Exception 是否是继承咱们的基类BaesException
    if ($exception instanceof BaseException) {
        // 自定义一个错误类Error 里面有一个错误的属性 
        // public static $errCodes = ['501' => '操做数据错误']
        // 而后还有个 根据错误码, 获取错误信息的方法 getErrorMsg
        $msg = Error::getErrorMsg($exception->errCode);
        return response()->json([
            'code' => $exception->code,
            'errCode' => $errCode,
            'msg' => $msg
        ]);
    }
    
    // 若是不是咱们想要定义的错误 不在生产环境的话,仍是返回错误页面
    if (env('APP_DEBUG')) {
        parent::render();
    }
    
    // 生产环境
    return Response()->json([
            'errCode' => 999,
            'msg' => '服务器内部错误'
        ], 501);
    
    }

复制代码
  • 最后建立Validate类继承BaseValidate
// createDeviceValidate.php

class CreateDeviceValidate extends BaseValidate {
    // 仍是填之前的规则
    protected $rule = [
        'gateway_sn' => 'required|exists:gateways,sn',
        'sn' => 'required|unique:devices,sn',
        'type' => 'required|positiveIntger',
        'mac' => 'required'
    ];

    // 信息填错误码就行了~
    protected $message = [
        'gateway_sn.required' => '213001',
        'gateway_sn.exists' => '213005',
        'sn.required' => '214001',
        'sn.unique' => '214002',
        'type.required' => '214005',
        'type.positive_intger' => '214006',
        'mac.required' => '214007'
    ];
}

复制代码
  • 最后控制器的写法
public function create(CreateDeviceValidate $createDeviceValidate)
    {
        // 就这样check咯 简单
        $createDeviceValidate->check();
    }

复制代码

结束 洒花

相关文章
相关标签/搜索