在 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 协议》,转载必须注明作者和本文链接
当神不再是我们的信仰,那么信仰自己吧,努力让自己变好,不辜负自己的信仰!
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 9

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

7年前 评论

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

7年前 评论

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

7年前 评论

这种格式对吗?

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

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

7年前 评论

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

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

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

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

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

@overtrue 哪种方式合适?

7年前 评论

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

7年前 评论

未填写
文章
42
粉丝
158
喜欢
713
收藏
347
排名:30
访问:22.2 万
私信
所有博文
社区赞助商