介绍
Laravel 提供了多个不同的渠道来验证你的应用接收的数据。默认情况下,Laravel基础控制器类使用一个ValidatesRequests trait,这个trait提供了验证HTTP请求数据非常多的非常有用的验证规则。
验证入门
为了学习Laravel的强大的验证特性,让我们来看一个简单的例子,这个例子验证了一个表单并且打印了错误信息给用户。
定义规则
首先,假设我们已经在app/Http/routes.php文件中定义了如下的路由:
// Display a form to create a blog post...
Route::get('post/create', 'PostController@create');
// Store a new blog post...
Route::post('post', 'PostController@store');
当然,GET路由将显示一个创建新博客的表单,POST路由将会将新的博客上传到数据库中。
创建新的控制权
接下来,让我们来看一下啊一个简单的处理这些路由的控制器。我们先不实现store方法:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Show the form the create a new blog post.
*
* @return Response
*/
public function create()
{
return view('post.create');
}
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate and store the blog post...
}
}
编写验证逻辑
现在我们可以来实现store方法了,并且在此方法中验证新的博客post。如果你查看过App\Http\Controllers\Controller类,你将看到类使用了ValidatesRequests trait。这个trait为你所有的控制器提供了非常实用的validate方法。
validate方法接收一个传入的HTTP 请求和一系列的验证规则。如果验证规则通过了,你的代码将会继续执行。一旦失败,将会抛出一个异常,并且对应的错误响应会自动的传回给用户。对于传统的HTTP请求来讲,一个重定向响应将会被生成,同时JSON响应将会被传递给AJAX请求。
为了更好的理解validate方法,让我们重新回来store方法:
/**
* Store a new blog post.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid, store in database...
}
正如你所看到的,我们传递给validate方法一个HTTP请求和我们想要的验证规则。同样,如果验证失败,相应的相应将会自动生成,如果验证通过,我们的控制器将会继续正常执行。
嵌套属性
如果你的HTTP请求包含嵌套参数,你可以使用点语法来特殊声明他们:
$this->validate($request, [
'title' => 'required|unique:posts|max:255',
'author.name' => 'required',
'author.description' => 'required',
]);
显示验证错误
那么,如果传递进来的请求参数没有通过验证怎么办?前面提及过,Laravel将会自动的将用户重定向会他们先前的路径。此外,所有的验证错误将会自动的刷新岛session中。
注意,我们并不需要在GET路由上为视图绑定错误信息。因为Laravel总是会自动的检查session数据上面的错误信息,并且当他们可用的时候自动的见过他们绑定到视图上。所以,在所有视图中的每个请求$error变量都是可用的,你可以假定$error变量一直存在并且可以安全的使用。$error是Illuminate\Support\MessageBag 的一个实例。更多关于这个对象的信息,可以参考相关文档。
因此,在我们的例子中,用户在验证失败后将会被重定向到控制器的create方法,我们可以来输出这段错误信息:
<!-- /resources/views/post/create.blade.php -->
<h1>Create Post</h1>
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<!-- Create Post Form -->
自定义错误格式
如果你希望在验证失败的时候能够自定义刷新岛session中的错误信息格式,你可以在基础控制器基类中重写 formatValidationErrors方法。不要忘记引入
Illuminate\
Contracts\Validation\Validator
类:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
abstract class Controller extends BaseController
{
use DispatchesJobs, ValidatesRequests;
/**
* {@inheritdoc}
*/
protected function formatValidationErrors(Validator $validator)
{
return $validator->errors()->all();
}
}
AJAX请求和验证
上例中,我们使用一个传统的表单来发送数据给应用。然而,许多应用使用AJAX请求。当在AJAX请求中使用validate方法时,Laravel将不会生成一个重定向请求。取而代之,Laravel将生成一个JSON请求,该请求包含所有的验证错误。这个JSON响应将会附带一个422HTTP状态码。
其他验证方法
手动创建验证
如果你不想要使用ValidatesRequests的trait中包含的validate方法,你可以使用Validator外观件手动创建一个validator实例。外观件的make方法生成了一个新的validator实例:
<?php
namespace App\Http\Controllers;
use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PostController extends Controller
{
/**
* Store a new blog post.
*
* @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中的错误信息。当使用这个方法,$error变量将会自动的将变量在你的视图中共享,允许你很方便的给用于显示错误。withErrors方法接收一个validator或者MessageBag或者PHP数组。
命名错误集合包
如果你在单个页面上有多个表单,那么$error变量到底显示的是哪个表单的验证错误呢?这时我们可以针对MessageBag进行命名,允许你从特殊的表单中取出错误信息。只需要简单的传递一个名字作为withErrors方法的第二个参数:
return redirect('register')
->withErrors($validator, 'login');
而后你可以通过以下方式来访问命名后的MessageBag实例:
{{ $errors->login->first('email') }}
Validation的after钩子
validator同样允许你在验证完成后附加一个回调。这样你可以方便的执行更多的验证,甚至给错误信息集合中添加更多的错误信息。使用方式如下:
$validator = Validator::make(...);
$validator->after(function($validator) {
if ($this->somethingElseIsInvalid()) {
$validator->errors()->add('field', 'Something is wrong with this field!');
}
});
if ($validator->fails()) {
//
}
表单请求验证
对于更加复杂的验证脚本,你也可以创建一个“表单请求”。
表单请求是包含有验证逻辑的自定义请求类。我们可以使用CLI命令 make:request来创建它:
php artisan make:request StoreBlogPostRequest
生成的类将会被防止在app/Http/Requests目录下,让我们在rules中增加一些validation规则:
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
写好后这些规则如何被应用呢??你只需要将在控制器方法中显示其类型就可以了,进来的请求表单会在控制器方法被调用前执行,保证了控制器代码的整洁:
/**
* Store the incoming blog post.
*
* @param StoreBlogPostRequest $request
* @return Response
*/
public function store(StoreBlogPostRequest $request)
{
// The incoming request is valid...
}
如果严重失败,会生成一个重定向的响应将用于重定向到上一页面。错误信息将会被刷新到session中,可以通过$error变量来显示他们。如果请求是一个AJAX请求,将会返回状态码为422的HTTP响应,包含一个JSON的严重错误信息。
授权表单请求
表单请求同样包含一个authorize方法,使用这个方法,你可以检查已认证用户是否拥有更新给定资源的授权。例如,如果一个用户尝试更新一个博客评论,那么如何判断该用户是否拥有这条评论呢?来看下面的例子:
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$commentId = $this->route('comment');
return Comment::where('id', $commentId)
->where('user_id', Auth::id())->exists();
}
注意上例中的route方法,这个方法授权你获取定义在路由中的URI参数,例如例子下面的{comment}参数。
Route::post('comment/{comment}');
如果authorize方法返回false,将会返回一个带有403状态码的HTTP响应,控制器后续的方法将不会被执行。
如果你计划在应用的其他地方任职逻辑,那么直接在authorize方法中返回true就行了。
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
自定义刷新到session中的ERROR格式
如果你希望自定义刷新到session中的验证错误的格式,重新你的请求基类(App\Http\Requests\Request)中的formatErrors方法,不要忘记在文件的顶端引入
Illuminate\
Contracts\Validation\Validator
类:
/**
* {@inheritdoc}
*/
protected function formatErrors(Validator $validator)
{
return $validator->errors()->all();
}
自定义错误信息
你可以通过重写messages方法来自定义错误信息。这个方法应该返回属性/规则对来对应错误信息:
/**
* Get the error messages for the defined validation rules.
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
错误信息的一些常用获取方法
validator实例调用了errors方法后,你将取得一个
Illuminate\
Support\MessageBag
实例,该实例可以提供一系列的便捷的方法来取得error信息。
取出一个字段中的第一条错误信息
使用first方法来去除给给定字段的第一条错误信息:
$messages = $validator->errors();
echo $messages->first('email');
取出一个字段的所有的错误信息:
如果你希望简单的取出一个字段所有的数组错误信息,使用get方法:
foreach ($messages->get('email') as $message) {
//
}
取出所有字段的所有错误信息:
foreach ($messages->all() as $message) {
//
}
判断某一字段的错误信息是否存在:
if ($messages->has('email')) {
//
}
取出带有格式的一条错误信息:
echo $messages->first('email', '<p>:message</p>');
取出带有格式的所有错误信息:
foreach ($messages->all('<li>:message</li>') as $message) {
//
}
自定义错误信息
如果需要,可以让验证使用自定义错误信息。有几种方式来自定义信息。第一种,你可以传递一个自定义信息作为Validator::make方法的第三个参数:
$messages = [
'required' => 'The :attribute field is required.',
];
$validator = Validator::make($input, $rules, $messages);
在这个例子中,:attribute前置参数在验证中将会由真正的字段替代,你可以在验证消息中使用其他的前置参数,例如:
$messages = [
'same' => 'The :attribute and :other must match.',
'size' => 'The :attribute must be exactly :size.',
'between' => 'The :attribute must be between :min - :max.',
'in' => 'The :attribute must be one of the following types: :values',
];
为一个给定的请求特殊化一个自定义信息
有时你希望只针对一个特殊的字段来自定义错误信息,你可以使用点语法,如下:
$messages = [
'email.required' => 'We need to know your e-mail address!',
];
在语言文件中特殊自定义信息
如果不想直接在代码中自定义错误消息的话,你可以在
resources
/
lang
/
xx
/
validation
.
php
语言温江中添加你的信息给custom数组:
'custom' => [
'email' => [
'required' => 'We need to know your e-mail address!',
],
],
可用的验证规则
略过。
有条件的添加规则(字段不知道是否存在)
在一些情况下,你希望只有当字段出现在请求中的时候再运行验证检查。快速完成这个,可以添加sometimes规则到你的规则列表:
$v = Validator::make($data, [
'email' => 'sometimes|required|email',
]);
例子中,email字段只有在它出现在$data数组中的时候才会验证。
复杂的有条件验证
有时你可能希望添加一个更加复杂的有条件验证,比如你希望在另一个字段大于100的时候才需要一个字段。或者只有当另一个字段存在的时候,另外两个字段才进行验证?很简单,我们先新建一个Validator实例:
$v = Validator::make($data, [
'email' => 'required|email',
'games' => 'required|numeric',
]);
让我们假设网站应用服务于玩具回收者,如果一个玩具回收折拥有超过100个玩具并且注册我们的网站,我们希望他们解释为啥他们有这么多玩具,例如,大概他们运行一个玩具二次销售商店,或者他们就是喜欢回收。为了有条件的添加这个需求,我们可以在Validator实例上使用sometimes方法。
$v->sometimes('reason', 'required|max:500', function($input) {
return $input->games >= 100;
});
传递给sometimes方法的第一个参数是我们希望选择性验证的字段。第二个参数使我们希望添加的规则。如果闭包(第三个参数)返回true,那么规则将会被添加,这使得复杂的验证变得非常简单,你甚至可以一次性为几个字段添加选择性的验证:
$v - > sometimes( [ 'reason' , 'cost' ] , 'required' , function ( $input ) { return $input - > games >= 100 ; } ) ;
自定义验证规则
略过。
英文原文地址:http://www.golaravel.com/laravel/docs/5.1/validation/#form-request-validation