想必总有过这种状况,你的前端小伙有时收到一个框架自带的报错,一脸懵逼,而后找你,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
以laravel 框架做为实例,TP5还有其余框架都有的~bash
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),能够自定义错误内容。
复制代码
// 这里关注在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' => '保存商品失败'])
}
}
复制代码
有了以上的异常类,在验证类这一块能够说是很是爽的~app
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 方法
}
复制代码
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);
}
复制代码
// 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();
}
复制代码