Laravel异步ajax表单请求数据验证422失败的解决方法

作者: 温新

分类: 【Laravel】

阅读: 3216

时间: 2020-12-13 16:38:58

需求

Laravel数据验证,最传统的是在控制器中进行验证,验证失败的错误信息会存储在session中,前端模板通过session来取出错误信息。控制器中大量的验证使用代码臃肿难看,Laravel中提供了优雅的写法Form Request,但是这将导致通过ajax请求表单数据验证报422错误。

另一个场景就是前后端分离,大量使用异步请求,传统的验证已无法适应。这些问题都可以通过异常来解决。使用异常来优雅的处理表单验证。

什么是Form Request

Laravel中每一个请求都会被封装成一个Request对象,Form Request对象包含了额外的验证逻辑及访问权限控制的自定义Request类。

使用Form Request验证

步骤一:生成

php artisan make:request TestRequest

步骤二:编写验证规则

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"><?</span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">namespace</span> <span style="box-sizing: border-box">App\Http\Requests</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Illuminate\Foundation\Http\FormRequest</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">class</span> <span style="box-sizing: border-box">UserRequest</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">extends</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">FormRequest</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(199, 146, 234)">public</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">function</span> <span style="box-sizing: border-box">authorize</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(199, 146, 234)">return</span> <span style="box-sizing: border-box;color: rgb(247, 118, 105)">true</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(199, 146, 234)">public</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">function</span> <span style="box-sizing: border-box">rules</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(199, 146, 234)">return</span> [</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'username'</span>  <span style="box-sizing: border-box">=></span>  <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'required|max:50'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        ];</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(199, 146, 234)">public</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">function</span> <span style="box-sizing: border-box">messages</span>()</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(199, 146, 234)">return</span> [</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'username.required'</span> <span style="box-sizing: border-box">=></span>  <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'用户名必填'</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        ];</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

步骤三:控制器中使用

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">App\Http\Requests\TestRequest</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(84, 110, 122)">// 依赖注入后会自动对表单数据进行验证</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">public</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">function</span> <span style="box-sizing: border-box">store</span>(<span style="box-sizing: border-box;color: rgb(130, 177, 255)">TestRequest</span> <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$request</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

到这里验证完成了,但是问题也来了。由于是ajax异步请求,那么就会发现,表单数据已经验证,同时也报了一个422错误。解决方法就是重写父类的failedValidation方法。

步骤四:重写父类failedValidation方法

在生成的TestRequest.php文件中重写父类方法,重写完成后就会看到熟悉的错误返回信息了。

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"><?</span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">namespace</span> <span style="box-sizing: border-box">App\Http\Requests</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Illuminate\Foundation\Http\FormRequest</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(84, 110, 122)"># 下面这三个引入不可省略</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Illuminate\Contracts\Validation\Validator</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Illuminate\Validation\ValidationException</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">use</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Symfony\Component\HttpFoundation\Response</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(199, 146, 234)">class</span> <span style="box-sizing: border-box">UserRequest</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">extends</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">FormRequest</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"> <span style="box-sizing: border-box;color: rgb(84, 110, 122)"># 此处省略验证规则与信息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(84, 110, 122)">// 重写ajax请求验证错误响应格式(防止验证422报错)</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(199, 146, 234)">protected</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">function</span> <span style="box-sizing: border-box">failedValidation</span>(<span style="box-sizing: border-box;color: rgb(130, 177, 255)">Validator</span> <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$validator</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(84, 110, 122)">// 此处自定义表单验证错误信息</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$data</span> <span style="box-sizing: border-box">=</span> [</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'code'</span> <span style="box-sizing: border-box">=></span> <span style="box-sizing: border-box;color: rgb(247, 118, 105)">10000</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(195, 232, 141)">'msg'</span> <span style="box-sizing: border-box">=></span> <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$validator</span><span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">errors</span>()<span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">first</span>(),</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        ];</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$respone</span> <span style="box-sizing: border-box">=</span> <span style="box-sizing: border-box;color: rgb(199, 146, 234)">new</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">Response</span>(<span style="box-sizing: border-box;color: rgb(222, 203, 107)">json_encode</span>(<span style="box-sizing: border-box;color: rgb(128, 203, 196)">$data</span>));</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(199, 146, 234)">throw</span> (<span style="box-sizing: border-box;color: rgb(199, 146, 234)">new</span> <span style="box-sizing: border-box;color: rgb(130, 177, 255)">ValidationException</span>(<span style="box-sizing: border-box;color: rgb(128, 203, 196)">$validator</span>, <span style="box-sizing: border-box;color: rgb(128, 203, 196)">$respone</span>))</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">errorBag</span>(<span style="box-sizing: border-box;color: rgb(128, 203, 196)">$this</span><span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">errorBag</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">redirectTo</span>(<span style="box-sizing: border-box;color: rgb(128, 203, 196)">$this</span><span style="box-sizing: border-box">-></span><span style="box-sizing: border-box;color: rgb(130, 177, 255)">getRedirectUrl</span>());</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

注意:Validator、ValidationException、Response这三个一定要引入,不然会报500错误。

我是小白,期待和优秀的你一起同行!

小白

2020年12月14日

请登录后再评论