10、基础组件 —— 表单验证

简介

   Laravel 提供了多种方法来验证请求输入数据。默认状况下,Laravel 的控制器基类使用 ValidatesRequests trait,该 trait 提供了便捷方法经过各类功能强大的验证规则来验证输入的 HTTP 请求。php

快速入门

   要掌握 Laravel 强大的验证特性,让咱们先看一个完整的验证表单并返回错误信息给用户的示例。laravel

   定义路由

    首先,咱们假定在 routes/web.php 文件中包含以下路由:git

// 显示建立博客文章表单...
Route::get('post/create', 'PostController@create');
// 存储新的博客文章...
Route::post('post', 'PostController@store');

     显然,GET 路由为用户显示了一个建立新的博客文章的表单,POST 路由将新的博客文章存储到数据库。web

   建立控制器

     接下来,让咱们看一个处理这些路由的简单控制器示例。咱们先将 store 方法留空:正则表达式

<?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 方法:apache

/**
 * 存储博客文章
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request){
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // 验证经过,存储到数据库...
}

     正如你所看到的,咱们只是传入指望的验证规则到 validate 方法。再强调一次,若是验证失败,相应的响应会自动生成。若是验证经过,控制器将会继续往下执行。json

注:实际执行代码以前,须要在数据库中建立 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,咱们能够看下这个 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|unique:posts|max:255',
        'body' => 'required',
    ];
}

注:你能够在 rules 方法签名签名中注入任何依赖,它们会经过服务容器自动解析。

     那么,验证规则如何生效呢?你所要作的就是在控制器方法中类型提示该请求类。这样表单输入请求会在控制器方法被调用以前被验证,这就是说你不须要将控制器方法和验证逻辑杂糅在一块儿:

/**
 * 存储输入的博客文章
 *
 * @param  StoreBlogPostRequest  $request
 * @return Response
 */
public function store(StoreBlogPost $request){
    // The incoming request is valid...

    // Retrieve the validated input data...
    $validated = $request->validated();
}

     若是验证失败,重定向响应会被生成并将用户退回上一个位置,错误信息也会被存储到一次性 Session 以便在视图中显示。若是是 AJAX 请求,带 422 状态码的 HTTP 响应将会返回给用户,该响应数据中还包含了 JSON 格式的验证错误信息。

   添加验证后钩子到表单请求

     若是你想要添加“验证后”钩子到表单请求,可使用 withValidator 方法。该方法接收完整的构造验证器,从而容许你在验证规则执行前调用任何验证器方法:

/**
 * 配置验证器实例.
 *
 * @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 方法,你能够经过该方法检查认证用户是否有权限更新指定资源。例如,若是用户尝试更新一条博客评论,那么他必须是该评论的全部者。举个例子:

/**
 * 断定用户是否有权限发起请求.
 *
 * @return bool
 * @translator laravelacademy.org
 */
public function authorize()
{
    $comment = Comment::find($this->route('comment'));
    return $comment && $this->user()->can('update', $comment);
}

     因为全部请求都继承自 Laravel 请求基类,咱们可使用 user 方法获取当前认证用户,还要注意上面这个例子中对 route 方法的调用。该方法赋予用户访问被调用路由 URI 参数的权限,好比下面这个例子中的 {comment} 参数:

Route::post('comment/{comment}');

     若是 authorize 方法返回 false,一个包含 403 状态码的 HTTP 响应会自动返回并且控制器方法将不会被执行。

     若是你计划在应用的其余部分调用受权逻辑,只需在 authorize 方法中简单返回 true 便可:

/**
 * 判断请求用户是否通过受权
 *
 * @return bool
 */
public function authorize(){
    return true;
}

注:你能够在 authorize() 方法签名中注入任何依赖,它们将会经过服务容器自动解析。

   自定义错误消息

     你能够经过重写 messages 方法自定义表单请求使用的错误消息,该方法应该返回属性/规则对数组及其对应错误消息:

/**
 * 获取被定义验证规则的错误消息
 *
 * @return array
 * @translator laravelacademy.org
 */
public function messages(){
    return [
        'title.required' => 'A title is required',
        'body.required'  => 'A message is required',
    ];
}

   自定义验证属性

     若是你想要将验证消息中的 :attribute 部分替换为自定义的属性名,能够经过重写 attributes 方法来指定自定义的名称。该方法会返回属性名及对应自定义名称键值对数组:

/**
 * Get custom attributes for validator errors.
 *
 * @return array
 */
public function attributes()
{
    return [
        'email' => 'email address',
    ];
}

   手动建立验证器

     若是你不想使用请求实例上的 validate 方法,可使用 Validator 门面手动建立一个验证器实例,该门面提供的 make 方法可用于生成一个新的验证器实例:

<?php

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

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();
        }

        // 存储博客文章...
    }
}

     传递给 make 方法的第一个参数是须要验证的数据,第二个参数是要应用到数据上的验证规则。

     检查请求没有经过验证后,可使用 withErrors 方法将错误数据存放到一次性 Session,使用该方法时,$errors变量重定向后自动在视图间共享,从而容许你轻松将其显示给用户,withErrors 方法接收一个验证器、或者一个 MessageBag ,又或者一个 PHP 数组。

   自动重定向

     若是你想要手动建立一个验证器实例,但仍然使用请求实例的 validate 方法提供的自动重定向,能够调用已存在验证器实例上的 validate 方法,若是验证失败,用户将会被自动重定向,或者,若是是 AJAX 请求的话,返回 JSON 响应:

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

   命名错误包

     若是你在单个页面上有多个表单,可能须要命名错误的 MessageBag,从而容许你为指定表单获取错误信息。只须要传递名称做为第二个参数给 withErrors 便可:

return redirect('register')
       ->withErrors($validator, 'login');

     而后你就能够从 $errors 变量中访问命名的 MessageBag 实例:

{{ $errors->login->first('email') }}

   验证钩子以后

     验证器容许你在验证完成后添加回调,这种机制容许你轻松执行更多验证,甚至添加更多错误信息到消息集合。使用验证器实例上的 after 方法便可:

$validator = Validator::make(...);

$validator->after(function($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', 'Something is wrong with this field!');
    }
});

if ($validator->fails()) {
    //
}

处理错误信息

   调用 Validator 实例上的 errors 方法以后,将会获取一个 Illuminate\Support\MessageBag 实例,该实例中包含了多种处理错误信息的便利方法。在全部视图中默认有效的 $errors 变量也是一个 MessageBag 实例。

   获取某字段的第一条错误信息

     要获取指定字段的第一条错误信息,可使用 first 方法:

$errors = $validator->errors();
echo $errors->first('email');

   获取指定字段的全部错误信息

     若是你想要简单获取指定字段的全部错误信息数组,使用 get 方法:

foreach ($errors->get('email') as $message) {
    //
}

     若是是一个数组表单字段,可使用 * 获取全部数组元素错误信息:

foreach ($errors->get('attachments.*') as $message) {
    //
}

   获取全部字段的全部错误信息

     要获取全部字段的全部错误信息,可使用 all 方法:

foreach ($errors->all() as $message) {
    //
}

   判断消息中是否存在某字段的错误信息

    has 方法可用于判断错误信息中是否包含给定字段:

if ($errors->has(’email’)) {
    //
}

   自定义错误信息

     若是须要的话,你可使用自定义错误信息替代默认的,有多种方法来指定自定义信息。首先,你能够传递自定义信息做为第三个参数给 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' => '邮箱地址不能为空!',
];

   在语言文件中指定自定义消息

     在不少案例中,你可能想要在语言文件中指定自定义消息而不是将它们直接传递给 Validator。要实现这个,添加消息到 resources/lang/xx/validation.php 语言文件的 custom 数组:

'custom' => [
    'email' => [
        'required' => '邮箱地址不能为空!',
    ],
],

   在语言文件中指定自定义属性

     若是你想要将验证消息的 :attribute 部分替换成自定义的属性名称,能够在语言文件 resources/lang/xx/validation.php 的 attributes 数组中指定自定义名称:

'attributes' => [
    'email' => '邮箱地址',
],

   在语言文件中指定自定义值

     有时候你可能须要将验证消息中的 :value 部分替换成自定义的表示值,例如,下面这个验证规则指定若是 payment_type 值是 cc 的话信用卡号不能为空:

$request->validate([
    'credit_card_number' => 'required_if:payment_type,cc'
]);

     若是这个验证规则验证失败了,将会生成以下错误消息:

The credit card number field is required when payment type is cc.

     若是你想要替换支付类型值 cc,能够在 validation 语言文件中定义一个 values 数组来指定自定义的表示值:

'values' => [
    'payment_type' => [
        'cc' => 'credit card'
    ],
],

     这样一来,若是验证规则验证失败,对应的错误信息以下:

The credit card number field is required when payment type is credit card.

验证规则大全

   下面是有效规则及其函数列表:

accepted:验证字段的值必须是 yes、on、1 或 true,这在「赞成服务协议」时颇有用。

active_url:验证字段必须是基于 PHP 函数 dns_get_record 的,有 A 或 AAAA 记录的值。

after:date:验证字段必须是给定日期以后的一个值,日期将会经过 PHP 函数 strtotime 传递:
'start_date' => 'required|date|after:tomorrow'

能够指定另一个与日期进行比较的字段,而不是传递一个日期字符串给 strtotime 执行:
strtotime
'finish_date' => 'required|date|after:start_date'

after_or_equal:date:验证字段必须是大于等于给定日期的值,更多信息,请参考 after:date 规则。

alpha:验证字段必须是字母。

alpha_dash:验证字段能够包含字母和数字,以及破折号和下划线。

alpha_num:验证字段必须是字母或数字。

array:验证字段必须是 PHP 数组。

bail:第一个验证规则验证失败则中止运行其它验证规则。

before:date:和 after:date 相对,验证字段必须是指定日期以前的一个数值,日期将会传递给 PHP strtotime 函数。

before_or_equal:date:验证字段必须小于等于给定日期。日期将会传递给 PHP 的 strtotime 函数。

between:min,max:验证字段大小在给定的最小值和最大值之间,字符串、数字、数组和文件均可以像使用 size 规则同样使用该规则:

'name' => 'required|between:1,20'

boolean:验证字段必须能够被转化为布尔值,接收 truefalse10"1" 和 "0" 等输入。

confirmed:验证字段必须有一个匹配字段 foo_confirmation,例如,若是验证字段是 password,必须输入一个与之匹配的 password_confirmation 字段。

date:验证字段必须是一个基于 PHP strtotime 函数的有效日期

date_equals:date:验证字段必须等于给定日期,日期会被传递到 PHP strtotime 函数。

date_format:format:验证字段必须匹配指定格式,可使用 PHP 函数date 或 date_format 验证该字段。

different:field:验证字段必须是一个和指定字段不一样的值。

digits:value:验证字段必须是数字且长度为 value 指定的值。

digits_between:min,max:验证字段数值长度必须介于最小值和最大值之间。

dimensions:验证的图片尺寸必须知足该规定参数指定的约束条件:有效的约束条件包括:min_widthmax_widthmin_heightmax_heightwidthheightratio

'avatar' => 'dimensions:min_width=100,min_height=200'
ratio 约束宽度/高度的比率,这能够经过表达式 3/2 或浮点数 1.5 来表示:
3/21.5
'avatar' => 'dimensions:ratio=3/2'

因为该规则要求多个参数,可使用 Rule::dimensions 方法来构造该规则:
Rule::dimensions
use Illuminate\Validation\Rule;

         Validator::make($data, [
            'avatar' => [
                         'required',
                         Rule::dimensions()->maxWidth(1000)->maxHeight(500)->ratio(3 / 2),
            ],
         ]);

distinct:处理数组时,验证字段不能包含重复值

'foo.*.id' => 'distinct'

email:验证字段必须是格式正确的电子邮件地址。

exists:table,column:验证字段必须存在于指定数据表。

                    基本使用:

'state' => 'exists:states' //若是 column 选项没有指定,将会使用字段名。

指定自定义列名:
column
'state' => 'exists:states,abbreviation'

有时,你可能须要为 exists 查询指定要使用的数据库链接,这能够在表名前经过.前置数据库链接来实现:
exists
'email' => 'exists:connection.staff,email'

若是你想要自定义验证规则执行的查询,可使用 Rule 类来定义规则。在这个例子中,咱们还以数组形式指定了验证规则,而不是使用 | 字符来限定它们:
Rule|
use Illuminate\Validation\Rule;

                  Validator::make($data, [
                   'email' => [
                              'required',
                              Rule::exists('staff')->where(function ($query) {
                                  $query->where('account_id', 1);
                              }),
                   ],
                  ]);

file:验证字段必须是上传成功的文件。

filled:验证字段若是存在则不能为空。

gt:field:验证字段必须大于给定 field 字段,这两个字段类型必须一致,适用于字符串、数字、数组和文件,和 size 规则相似

gte:field:验证字段必须大于等于给定 field 字段,这两个字段类型必须一致,适用于字符串、数字、数组和文件,和 size 规则相似

image:验证文件必须是图片(jpeg、png、bmp、gif 或者 svg)

in:foo,bar…:验证字段值必须在给定的列表中,因为该规则常常须要咱们对数组进行 implode,咱们可使用 Rule::in 来构造这个规则:

use Illuminate\Validation\Rule;

           Validator::make($data, [
            'zones' => [
               'required',
               Rule::in(['first-zone', 'second-zone']),
            ],
           ]);

in_array:另外一个字段,验证字段必须在另外一个字段值中存在。

integer:验证字段必须是整型。

ip:验证字段必须是IP地址。

ipv4:验证字段必须是IPv4地址。

ipv6:验证字段必须是IPv6地址。

json:验证字段必须是有效的JSON字符串

lt:field:验证字段必须小于给定 field 字段,这两个字段类型必须一致,适用于字符串、数字、数组和文件,和 size 规则相似

lte:field:验证字段必须小于等于给定 field 字段,这两个字段类型必须一致,适用于字符串、数字、数组和文件,和 size 规则相似

max:value:验证字段必须小于等于最大值,和字符串、数值、数组、文件字段的 size 规则使用方式同样。

mimetypes:text/plain…:验证文件必须匹配给定的 MIME 文件类型之一:

为了判断上传文件的 MIME 类型,框架将会读取文件内容来猜想 MIME 类型,这可能会和客户端 MIME 类型不一样。'video' => 'mimetypes:video/avi,video/mpeg,video/quicktime' //

 

mimes:foo,bar,…:验证文件的 MIME 类型必须是该规则列出的扩展类型中的一个

                MIME 规则的基本使用:

'photo' => 'mimes:jpeg,bmp,png'

                尽管你只是指定了扩展名,该规则实际上验证的是经过读取文件内容获取到的文件 MIME 类型。

                完整的 MIME 类型列表及其相应的扩展能够在这里找到:http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

min:value:与 max:value 相对,验证字段必须大于等于最小值,对字符串、数值、数组、文件字段而言,和 size 规则使用方式一致。

not_in:foo,bar,…:验证字段值不能在给定列表中,和 in 规则相似,咱们可使用 Rule::notIn 方法来构建规则:

use Illuminate\Validation\Rule;

                Validator::make($data, [
                 'toppings' => [
                   'required',
                   Rule::notIn(['sprinkles', 'cherries']),
                 ],
                ]);

not_regex:pattern:验证字段不能匹配给定正则表达式

              注:使用 regex/not_regex 模式时,规则必须放在数组中,而不能使用管道分隔符,尤为是正则表达式中包含管道符号时。

nullable:验证字段能够是 null,这在验证一些能够为 null 的原始数据如整型或字符串时颇有用。

numeric:验证字段必须是数值

present:验证字段必须出如今输入数据中但能够为空。

regex:pattern:验证字段必须匹配给定正则表达式。

              该规则底层使用的是 PHP 的 preg_match 函数。所以,指定的模式须要遵循 preg_match 函数所要求的格式而且包含有效的分隔符。例如 'email' => 'regex:/^.+@.+$/i'

         注:使用 regex/not_regex 模式时,规则必须放在数组中,而不能使用管道分隔符,尤为是正则表达式中包含管道符号时。

required:验证字段值不能为空,如下状况字段值都为空:

  • 值为null
  • 值是空字符串
  • 值是空数组或者空的 Coutable 对象
  • 值是上传文件但路径为空

required_if:anotherfield,value,…:验证字段在 anotherfield 等于指定值 value 时必须存在且不能为空。

                                  若是你想要为 required_if 规则构造更复杂的条件,可使用 Rule::requiredIf 方法,该方法接收一个布尔值或闭包。

                                  当传递一个闭包时,会返回 true 或 false 以代表验证字段是不是必须的:

use Illuminate\Validation\Rule;

                                  Validator::make($request->all(), [
                                      'role_id' => Rule::requiredIf($request->user()->is_admin),
                                  ]);

                                  Validator::make($request->all(), [
                                      'role_id' => Rule::requiredIf(function () use ($request) {
                                           return $request->user()->is_admin;
                                      }),
                                  ]);

required_unless:anotherfield,value,…:除非 anotherfield 字段等于 value,不然验证字段不能空。

required_with:foo,bar,…:验证字段只有在任一其它指定字段存在的状况才是必须的。

required_with_all:foo,bar,…:验证字段只有在全部指定字段存在的状况下才是必须的。

required_without:foo,bar,…:验证字段只有当任一指定字段不存在的状况下才是必须的。

required_without_all:foo,bar,…:验证字段只有当全部指定字段不存在的状况下才是必须的。

same:field:给定字段和验证字段必须匹配。

size:value:验证字段必须有和给定值 value 相匹配的尺寸/大小,对字符串而言,value 是相应的字符数目;对数值而言,value 是给定整型值;对数组而言,value 是数组长度;对文件而言,value 是相应的文件千字节数(KB)。

starts_with:foo,bar,...:验证字段必须以某个给定值开头。

string:验证字段必须是字符串,若是容许字段为空,须要分配 nullable 规则到该字段。

timezone:验证字符必须是基于 PHP 函数 timezone_identifiers_list 的有效时区标识

unique:table,column,except,idColumn:验证字段在给定数据表上必须是惟一的,若是不指定 column 选项,字段名将做为默认 column

                                    1)指定自定义列名: 'email' => 'unique:users,email_address'

                                    2)自定义数据库链接:有时候,你可能须要自定义验证器生成的数据库链接,正如上面所看到的,设置 unique:users 做为验证规则将会使用默认数据库链接来查询数据库。要覆盖默认链接,在数据表名后使用“.”指定链接:

'email' => 'unique:connection.users,email_address'

                                    3)强制一个忽略给定 ID 的惟一规则:有时候,你可能但愿在惟一检查时忽略给定 ID,例如,考虑一个包含用户名、邮箱地址和位置的”更新属性“界面,你将要验证邮箱地址是惟一的,然而,若是用户只改变用户名字段而并无改变邮箱字段,你不想要由于用户已经拥有该邮箱地址而抛出验证错误,你只想要在用户提供的邮箱已经被别人使用的状况下才抛出验证错误。

                                       要告诉验证器忽略用户 ID,可使用 Rule 类来定义这个规则,咱们还要以数组方式指定验证规则,而不是使用 |来界定规则:

use Illuminate\Validation\Rule;

                                       Validator::make($data, [
                                           'email' => [
                                               'required',
                                                Rule::unique('users')->ignore($user->id),
                                            ],
                                        ]);

除了传递模型实例主键值到 ignore 方法以外,你还能够传递整个模型实例。Laravel 会自动从模型实例中解析出主键值:
ignore
Rule::unique('users')->ignore($user)

若是你的数据表使用主键字段不是 id,能够在调用 ignore 方法的时候指定字段名称:
idignore
'email' => Rule::unique('users')->ignore($user->id, 'user_id')

默认状况下,unique 规则会检查与要验证的属性名匹配的列的惟一性。不过,你能够指定不一样的列名做为 unique方法的第二个参数:
uniqueunique
Rule::unique('users', 'email_address')->ignore($user->id)

                                     4)添加额外的 where 子句:

                                           使用 where 方法自定义查询的时候还能够指定额外查询约束,例如,下面咱们来添加一个验证 account_id 为 1 的约束:

'email' => Rule::unique('users')->where(function ($query) {
                                                        $query->where('account_id', 1);
                                                    })

url:验证字段必须是有效的 URL。

uuid:该验证字段必须是有效的 RFC 4122(版本 一、三、4 或 5)全局惟一标识符(UUID)。

添加条件规则

   存在时验证

     在某些场景下,你可能想要只有某个字段存在的状况下进行验证检查,要快速实现这个,添加 sometimes 规则到规则列表:

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

     在上例中,email 字段只有存在于 $data 数组时才会被验证。

注:若是你尝试验证一个老是存在但可能为空的字段时,参考 可选字段注意事项。

   复杂条件验证

     有时候你可能想要基于更复杂的条件逻辑添加验证规则。例如,你可能想要只有在另外一个字段值大于 100 时才要求一个给定字段是必须的,或者,你可能须要只有当另外一个字段存在时两个字段才都有给定值。添加这个验证规则并非一件头疼的事。首先,建立一个永远不会改变的静态规则到 Validator 实例:

$v = Validator::make($data, [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

     假定咱们的 Web 应用服务于游戏收藏者。若是一个游戏收藏者注册了咱们的应用并拥有超过 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;
});

注:传递给闭包的 $input 参数是 Illuminate\Support\Fluent 的一个实例,可用于访问输入和文件。

验证数组输入

     验证表单数组输入字段再也不是件痛苦的事情,例如,若是进入的 HTTP 请求包含 photos[profile] 字段,能够这么验证:

$validator = Validator::make($request->all(), [
    'photos.profile' => 'required|image',
]);

     咱们还能够验证数组的每一个元素,例如,要验证给定数组输入中每一个 email 是不是惟一的,能够这么作(这种针对提交的数组字段是二维数组,如 person[][email] 或 person[test][email]):

$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);

     相似地,在语言文件中你也可使用 * 字符指定验证消息,从而可使用单个验证消息定义基于数组字段的验证规则:

'custom' => [
    'person.*.email' => [
        'unique' => '每一个人的邮箱地址必须是惟一的',
    ]
],

自定义验证规则

   使用 Rule 对象

     如上所述,Laravel 提供了多种有用的验证规则;不过,你可能仍是须要指定一些本身的验证规则。注册自定义验证规则的一种方法是使用规则对象,要生成一个新的规则对象,可使用 Artisan 命令 make:rule。下面咱们使用这个命令来生成一个用于验证字符串是不是大写的规则,生成的新规则对象类位于 app/Rules 目录:

php artisan make:rule Uppercase

     规则建立以后,就能够定义行为方法,一个规则对象包含两个方法:passes 和 messagepasses 方法接收属性值和名称,而且基于属性值是否有效返回 true 或 falsemessage 方法用于在验证失败时返回验证错误消息:

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

     固然,你能够在 message 方法中调用辅助函数 trans 来返回一个在语言文件中定义的错误消息:

/**
 * Get the validation error message.
 *
 * @return string
 */
public function message()
{
    return trans('validation.uppercase');
}

     规则定义好以后,就能够将其以规则对象实例的方式和其余验证规则一块儿提供给验证器:

use App\Rules\Uppercase;

$request->validate([
    'name' => ['required', new Uppercase],
]);

   使用闭包

     若是在整个应用只须要一次自定义规则的功能,可使用闭包替代规则对象。该闭包接收属性名、属性值以及验证失败时调用的 $fail 回调:

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function($attribute, $value, $fail) {
            if ($value === 'foo') {
                return $fail($attribute.' is invalid.');
            }
        },
    ],
]);

   使用扩展

     另外一个注册自定义验证规则的方式是使用 Validator 门面上的 extend 方法。咱们在某个服务提供者(如 AppServiceProvider)中使用该方法注册一个自定义验证规则:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 启动应用服务
     *
     * @return void
     */
    public function boot()
    {
        Validator::extend('foo', function($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }

    /**
     * 注册服务提供者
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

     自定义验证器闭包接收四个参数:要验证的属性名称、属性值、传递给规则的参数数组以及 Validator 实例。

     你还能够传递类和方法到 extend 方法而不是闭包:

Validator::extend('foo', 'FooValidator@validate');

   定义错误信息

     你还须要为自定义规则定义错误信息。你可使用内联自定义消息数组或者在验证语言文件中添加条目来实现这一功能。消息应该被放到数组的第一维,而不是在只用于存放属性指定错误信息的 custom 数组内:

"foo" => "Your input was invalid!",
"accepted" => "The :attribute must be accepted.",
// 验证错误信息其它部分...

     当建立一个自定义验证规则时,你可能有时候须要为错误信息定义自定义占位符,能够经过建立自定义验证器而后调用 Validator 门面上的 replacer 方法来实现。在服务提供者的 boot 方法中编写以下代码:

/**
 * 启动应用服务
 *
 * @return void
 * @translator laravelacademy.org
 */
public function boot(){
    Validator::extend(...);
    Validator::replacer('foo', function($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

   隐式扩展

     默认状况下,被验证的属性若是没有提供或者验证规则为 required 而值为空,那么正常的验证规则,包括自定义扩展将不会执行。例如,unique 规则将不会检验 null 值:

$rules = ['name' => 'unique'];
$input = ['name' => null];
Validator::make($input, $rules)->passes(); // true

     若是要求即便为空时也要验证属性,则必需要暗示属性是必须的,要建立一个隐式扩展,可使用 Validator::extendImplicit() 方法:

Validator::extendImplicit('foo', function($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});

     注:一个隐式扩展仅仅暗示属性是必须的,至于它究竟是缺失的仍是空值这取决于你。

相关文章
相关标签/搜索