在 Lumen 中自定义表单验证返回消息

  • lumen的控制器中我们验证表单参数,如:
    public function store(Request $request)
    {
        $this->validate(
            $request,
            ['name' =>'required'],
            ['name.required' => '请填上你的大名']
        );
    }
  • 如果未通过,会返回这样格式的json响应
    {
        "name": [
                "请填上你的大名"
        ]
    }
  • 而我们开发 API 通过返回的响应消息不是这样的,这时候我们就可以通过在\App\Http\Controllers\Controller重写throwValidationException方法实现自定义消息。比如我就重写成这样子。
    protected function throwValidationException(Request $request, $validator)
    {
        $response = [
            'code' => 400,
            'msg'  => $validator->errors()->first(),
            'data' => []
        ];
         throw new ValidationException($validator, $response);
    }
  • 这里最重要的就是抛出了一个ValidationException异常,后面会说。可以看到主要就是通过验证器,获取错误消息,自己构造了一个响应数组。这时候返回的消息就变成了:
    {
     "code": 400,
     "msg": "请填上你的大名",
     "data": []
    }
  • 这样子就基本 OK 了,接下来说一说内部是怎么运行的吧。
    1. 访问index.php页面,执行到$app->run()
      file
    2. run方法里的dispatch方法负责分发路由
      file
    3. 点开dispatch方法,可以看到里面捕获了异常,再往里面看看
      file
    4. 点开sendExceptionToHandler方法看到里面有一个handler对面,我们打印看看(可以看到里面有一个dontReport属性,这里面应该是一个特殊处理的异常类。)
      file
      file
    5. sendExceptionToHandler里面的return $handler->render($this->make('request'), $e);为主要处理方法,点开render
      file
      • 这个方法里面,如果抛出的异常对象的原型是ValidationException类型且getResponse()返回内容
      • 就会直接返回我们定义的response而不会抛出异常视图。
      • return $this->prepareResponse($this->sendExceptionToHandler($e)); 通过sendExceptionToHandler获取到了错误消息数组,
      • prepareResponse方法把数组转换成了Response对象
      • 几个return之后我们又回到了run方法,得到了响应并进入Response::send()方法
        file
    6. send方法里有一个sendContent方法里直接输出了content,这样就基本完成消息输出
      file
本作品采用《CC 协议》,转载必须注明作者和本文链接
当神不再是我们的信仰,那么信仰自己吧,努力让自己变好,不辜负自己的信仰!
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 9

@rufo 你是否在App\Http\Controllers\Controlller重写了throwValidationException方法,最后附上你的代码截图

6年前 评论

@rufo 刚看了版本声明,
5.5 重写这个方法
file

6年前 评论

@施国鹏 额。。。ok,我看下呢

6年前 评论

这种格式对吗?

{
 "code": 400,
 "msg": "请填上你的大名",
 "data": []
}

他的用户名和密码都没填要怎么报?一次报一个?

6年前 评论

@qufo 我是报第一个错误,正常逻辑下是这样的。

$response = [
        'code' => 400,
        'msg'  => $validator->errors()->first(),
        'data' => []
    ];
// 如果你想知道所有错误,自己组装错误格式了
$msg = '';
foreach ($validator->errors as $error) {
     $msg .= $error;
}
6年前 评论

@施国鹏 报成这样会不会更好些?

{
  "errors": {
    "username": [
      "username 必须是 11 位."
    ],
    "password": [
      "password 的最小长度为 6 字符"
    ]
  }
}

这样我们能知道出错了,还能知道错误有两个,还知道其中的 username 错误只有一项,就是得是11位(手机).若有其他的,比如用户名必须包含 @ 符号,也可以写在那里。
把错误消息做下简单替换(username 替换成页面或者App上输入框的 Label),就可以显示给终端用户看了。

@overtrue 哪种方式合适?

6年前 评论

@qufo 不在于我,看你的需求。 我的需求是只要知道是否存在错误,并且返回错误消息就行了。所以我只要从$validator->errors()->first()(错误消息是在你在验证中填入的)里取出第一条错误消息就可以了,如果还有错误,那就另外说。
就像你的在应用程序中一样,你在 app 登录,你的密码,手机验证码都错了,这时候,我相信大多数的都不是提示所有错误消息,更多的是提示手机验证码错误了,只有一个消息,更好处理,
app 获取服务器的消息时,只要code不是200,不管如何,都弹出一个消息框,消息框的内容就是msg,这样子更多方便使用。

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
39
粉丝
156
喜欢
701
收藏
333
排名:31
访问:22.0 万
私信
所有博文
社区赞助商