ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## laravel表单验证器 ## 验证表单请求 ### 创建表单请求验证 面对更复杂的情况,您可以创建一个「表单请求」来应对更复杂的验证逻辑。表单请求是一个包含了验证逻辑的自定义请求类。要创建一个表单请求类,请使用`make:request`Artisan CLI 命令: ~~~php php artisan make:request StoreBlogPost ~~~ 该命令生成的类将被置于`app/Http/Requests`目录中。如果这个目录不存在,在您运行`make:request`命令后将会创建这个目录。让我们添加一些验证规则到`rules`方法中: ~~~php /** * 获取应用于请求的规则 * * @return array */ public function rules() { return [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]; } ~~~ > 技巧:您可以向`rules`方法传入所需的任何依赖项。它们将被 Laravel[服务容器](https://learnku.com/docs/laravel/8.x/container)自动解析。 所以,验证规则是如何运行的呢?你所需要做的就是在控制器方法中类型提示传入的请求。在调用控制器方法之前验证传入的表单请求,这意味着你不需要在控制器中写任何验证逻辑: ~~~php /** * 存储传入的博客文章 * * @param StoreBlogPost $request * @return Response */ public function store(StoreBlogPost $request) { // 传入的请求通过验证... // 获取通过验证的数据... $validated = $request->validated(); } ~~~ 如果验证失败,就会生成一个让用户返回到先前的位置的重定向响应。这些错误也会被闪存到 session 中,以便这些错误都可以在页面中显示出来。如果传入的请求是 AJAX,会向用户返回具有 422 状态代码和验证错误信息的 JSON 数据的 HTTP 响应。 #### 在表单请求后添加钩子 如果你想在表单请求「之后」添加钩子,可以使用`withValidator`方法。这个方法接收一个完整的验证构造器,允许你在验证结果返回之前调用任何方法: ~~~php /** * 配置验证实例 * * @param \Illuminate\Validation\Validator $validator * @return void */ public function withValidator($validator) { $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); } ~~~ ### 表单请求授权验证 表单请求类内也包含了`authorize`方法。在这个方法中,你可以检查经过身份验证的用户确定其是否具有更新给定资源的权限。比方说,你可以判断用户是否拥有更新文章评论的权限: ~~~php /** * 判断用户是否有请求权限 * * @return bool */ public function authorize() { $comment = Comment::find($this->route('comment')); return $comment && $this->user()->can('update', $comment); } ~~~ 由于所有的表单请求都是继承了 Laravel 中的请求基类,所以我们可以使用`user`方法去获取当前认证登录的用户。同时请注意上述例子中对`route`方法的调用。这个方法允许你在被调用的路由上获取其定义的 URI 参数,譬如下面例子中的`{comment}`参数: ~~~php Route::post('comment/{comment}'); ~~~ 如果`authorize`方法返回`false`,则会自动返回一个包含 403 状态码的 HTTP 响应,也不会运行控制器的方法。 如果你打算在应用程序的其它部分处理授权逻辑,只需从`authorize`方法返回`true`: ~~~php /** * 判断用户是否有请求权限 * * @return bool */ public function authorize() { return true; } ~~~ > Tip:你可以向`authorize`方法传入所需的任何依赖项。他们会自动被 Laravel 提供的[服务容器](https://learnku.com/docs/laravel/8.x/container)自动解析。 ## 手动创建验证器 如果您不想再请求中使用`validate`方法,您可以使用`Validator`[门面](https://learnku.com/docs/laravel/8.x/facades)手动创建一个验证器实例。门面中的`make`方法将会生成一个新的验证器实例: ~~~php <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; class PostController extends Controller { /** * 存储一篇博客文章 * * @param Request $request * @return Response */ public function store(Request $request) { $validator = Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ]); if ($validator->fails()) { return redirect('post/create') ->withErrors($validator) ->withInput(); } // Store the blog post... } } ~~~ `make`方法中的第一个参数是期望校验的数据。第二个参数是应用到数据上的校验规则。 如果校验失败,您可以使用`withErrors`方法将错误信息闪存至 session 中。使用该方法时,`$errors`会自动与之后的视图共享,您可以很方便将其回显给用户。`withErrors`方法接受验证器实例,`MessageBag`或是 PHP`数组`。 ### 自动重定向 如果您想要在手动创建验证器实例的同时,使用请求的`validate`方法的自动重定向功能,那么您可以在现有的验证器实例上调用`validate`方法。如果校验失败,用户将被自动重定向,或在 AJAX 请求下,将会返回一个 JSON 响应: ~~~php Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ])->validate(); ~~~ 如果校验失败,您可以使用`validateWithBag`方法将错误信息存储到[命名错误包](https://learnku.com/docs/laravel/8.x/validation/9374#named-error-bags)中。 ~~~php Validator::make($request->all(), [ 'title' => 'required|unique:posts|max:255', 'body' => 'required', ])->validateWithBag('post'); ~~~ ### 命名错误包 如果您的一个页面中存在多个表单,您可以为错误的`MessageBag`命名,用于检索指定表单的错误信息。只需将名称作为`withErrors`的第二个参数传递给它: ~~~php return redirect('register') ->withErrors($validator, 'login'); ~~~ 您可以通过`$errors`变量访问命名后的`MessageBag`实例: ~~~php {{ $errors->login->first('email') }} ~~~ ### 验证后钩子 验证器允许您在完成验证操作后执行附加的回调。以便您处理下一步的验证,甚至是往信息集合中添加更多的错误信息。您可以在验证器实例上使用`after`方法以实现之: ~~~php $validator = Validator::make(...); $validator->after(function ($validator) { if ($this->somethingElseIsInvalid()) { $validator->errors()->add('field', 'Something is wrong with this field!'); } }); if ($validator->fails()) { // } ~~~