简介
Laravel 提供了多种方法来验证请求输入数据。默认情况下,Laravel 的控制器基类使用 ValidatesRequests trait,该 trait 提供了便捷方法通过各种功能强大的验证规则来验证输入的 HTTP 请求。
快速入门
先看一个完整的验证表单并返回错误信息给用户的示例。
定义路由
首先,我们假定在 routes/web.php 文件中包含如下路由:
// 显示创建博客文章表单...
Route::get('post/create', 'PostController@create');
// 存储新的博客文章...
Route::post('post', 'PostController@store');
这里,GET 路由为用户显示了一个创建新的博客文章的表单,POST 路由将新的博客文章存储到数据库。
创建控制器
接下来,让我们看一个处理这些路由的简单控制器示例。我们先将 store 方法留空。
app/Http/Controllers/PostController.php 文件:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* 显示创建新的博客文章的表单
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* 存储新的博客文章
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// 验证并存储博客文章...
}
}
编写验证逻辑
现在我们准备用验证新博客文章输入的逻辑填充 store 方法。我们使用 Illuminate\Http\Request 对象提供的 validate 方法来实现这一功能,如果验证规则通过,代码将会继续往下执行;反之,如果验证失败,将会抛出一个异常,相应的错误响应也会自动发送给用户。
在这个传统的 HTTP 请求案例中,将会生成一个重定向响应,如果是 AJAX 请求则会返回一个 JSON 响应。
要更好地理解 validate 方法,让我们回顾下 store 方法:
/**
* 存储博客文章
*
* @param Request $request
* @return Response
*/
public function store(Request $request){
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// 验证通过,存储到数据库...
}
我们只是传入期望的验证规则到 validate 方法。再强调一次,如果验证失败,相应的响应会自动生成。如果验证通过,控制器将会继续往下执行。
注:实际执行代码之前,需要在数据库中创建 posts 数据表,因为这里用到了 unique:posts 这个验证规则,该规则会去数据库中查询传入标题是否已存在以保证唯一性。
首次验证失败后中止后续规则验证
有时候你可能想要在首次验证失败后停止检查该属性的其它验证规则,要实现这个功能,可以在规则属性中分配 bail 作为首规则:
$request->validate([
'title' => 'bail|required|unique:posts|max:255',
'body' => 'required',
]);
在这个例子中,如果 title 属性上的 required 规则验证失败,则不会检查 unique 规则,规则会按照分配顺序依次进行验证。
嵌套属性注意事项
如果 HTTP 请求中包含“嵌套”参数,可以使用“.”在验证规则中指定它们:
$request->validate([
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.desc' => 'required',
]);
这样的验证规则适用于验证如下请求:
<form method="POST" action="{
{route('posts.store')}}">
{
{csrf_field()}}
<input type="text" name="title"/>
<input type="text" name="author[name]"/>
<input type="text" name="author[desc]"/>
<textarea cols="20" rows="5" name="body"></textarea>
<button type="submit">submit</button>
</form>
显示验证错误信息
如果验证不通过,Laravel 将会自动将用户重定向回上一个位置。此外,所有验证错误信息会自动存放到一次性 Session。
注意我们并没有在 GET 路由中显式绑定错误信息到视图。这是因为 Laravel 总是从 Session 数据中检查错误信息,而且如果有的话会自动将其绑定到视图。所以,值得注意的是每次请求的所有视图中总是存在一个$errors 变量,从而允许你在视图中方便而又安全地使用。$errors 变量是一个Illuminate\Support\MessageBag 实例。
注:$errors 变量会通过 web 中间件组中的 Illuminate\View\Middleware\ShareErrorsFromSession 中间件绑定到视图,如果使用了该中间件,那么 $errors 变量在视图中总是有效,从而方便你随时使用。
所以,在我们的例子中,验证失败的话用户将会被重定向到控制器的 create 方法,从而允许我们在视图中显示错误信息:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{
{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
如果验证失败的话,跳转回表单页面的同时会显示错误信息。
可选字段注意事项
默认情况下,Laravel 自带了 TrimStrings 和 ConvertEmptyStringsToNull 中间件,这两个中间件位于 App\Http\Kernel 类的全局中间件堆栈中,因为这个原因,你需要经常将“可选”的请求字段标记为 nullable —— 如果你不想让验证器将 null 判定为无效的话。
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
'publish_at' => 'nullable|date',
]);
在这个例子中,我们指定 publish_at 字段可以为 null 或者有效的日期格式。如果 nullable 没有被添加到验证规则,验证器会将 null 判定为无效日期。
AJAX 请求&验证
在上面的例子中,我们使用了传统的表单来发送数据到应用。不过,现实场景中,很多应用使用 AJAX 请求。
在 AJAX 请求中使用 validate 方法时,Laravel 不会生成重定向响应。取而代之的,Laravel 生成一个包含验证错误信息的 JSON 响应。该 JSON 响应会带上一个 HTTP 状态码 422。
复杂表单验证
创建表单请求
对于更复杂的验证场景,你可能想要创建一个“表单请求”。表单请求是包含验证逻辑的自定义请求类,要创建表单验证类,可以使用 Artisan 命令 make:request。
php artisan make:request StoreBlogPost
生成的类位于 app/Http/Requests 目录下,如果该目录不存在,运行 make:request 命令时会替我们生成。接下来我们添加少许验证规则到该类的 rules 方法:
/**
* 获取请求的验证规则
*
* @return array
*/
public function rules(){
return [
'title' => 'required|