19.1 表单快速验证

快速验证方法,适合小规模的单独验证。

1、首先,创建两个路由,一个是表单的页面,另一个是表单提交后的处理页面:

  1. //表单页
  2. Route::get('/task/form','TaskController@form');
  3. //接收页
  4. Route::post('/task/receive','TaskController@receive');

2、然后,创建一个页面 form.blade.php,来作为表单提交的演示页面:

<form action="/task/receive" method="post">
    @csrf
    用户名:<input type="text" name="username" value="{{old('username')}}">
    密码:<input type="password" name="password">
    <button type="submit">提交</button>
</form>

{{old(‘username’)}}:表示回调后,自动填充已经填写的信息。

3、接下来,在 TaskController.php 控制类中,写入方法 receive() ,通过 Request 对象来实现字段验证,如下:

//Request 是 Illuminate\Http\Request 下的
public function receive(Request $request)
{
    //验证请求方式
    //左边为验证字段,右边为验证规则,每个规则竖线隔开
    //比如required 不得为空,min 不等小于,max 不得大于
    $request->validate([
        'username' => 'required|min:2|max:10',
        'password' => 'required|min:6',
    ]);
    //只有通过才能执行下面的语句,否则返回表单页
    return '恭喜验证通过!';
}

4、如果验证没有被通过,会自动重定向到提交页,并将错误信息存储到session 中。

其内部操作是通过中间件实现的,其中间件的位置:Illuminate\View\Middleware\ShareErrorsFromSession,文件路径:vendor\laravel\framework\src\Illuminate\View\Middleware\ShareErrorsFromSession.php

打开这个文件,可以看到,有一个方法返回的是一个名为 errors 的参数。在前端页面,可以使用该参数进行各种操作。

如遍历打印错误信息:

{{--如果有验证失败的错误信息, any()=1 --}}
@if ($errors->any())
    <div>
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

也可以单独设置错误信息,使用 @error 命令:

@error('username')
    <div>{{ $message }} : 用户名非法!</div>
@enderror

@error('password')
    <div>{{ $message }} : 密码非法!</div>
@enderror

5、关于规则,还有其它写法,具体如下:

//数组方式验证
$request->validate([
    'username' => ['required', 'min:2', 'max:10'],
    'password' => ['required', 'min:6']
]);

这里注意,中间还是以冒号间隔。

19.2 验证类的使用

所谓验证类,是将验证规则写在一个验证类中,然后进行调用。

1、创建验证类的方法:使用命令创建验证类

php artisan make:request Form

最后的Form是验证类的类名,可以根据实际情况修改。

然后即可在 app/http 目录下,新建一个名为 Requests 的文件,验证类 Form.php 就在该文件下。

2、验证类 Http\Request\Form.php 创建好之后,会提供两个固定方法;

public function authorize()
{
    //默认false,为关闭授权,关闭状态会403
    //比如判断这个用户是否有操作权限
    return true;
}

public function rules()
{
    return [
        //规则
    ];
}

然后在上面的 rules() 方法中,写入验证规则:

public function rules()
{
    return [
        //规则如下
        'username' => 'required|min:2|max:10',
        'password' => 'required|min:6',
    ];
}

3、在控制器端,直接使用验证类进行验证即可,其它和快速验证一样;

public function receive(Form $request)
{
    //通过验证类验证
    $request->validated();

    //只有通过才能执行下面的语句,否则返回表单页
    return '恭喜验证通过!';
}

这里注意,控制器的方法的参数,是Form 中的$request。

以下几种方法是已经实现的,可以重构修改。

4、在请求验证之前,可以修改提交的请求数据,在验证类创建prepareForValidation()实现:

protected function prepareForValidation()
{
    $this->merge([
        'username' => 'Mr.Lee'
    ]);
}

这时,不管前端提交的username是什么,都没用。

5、默认错误提示是英文的,如果想设置成中文提示,可在验证类创建message()实现;

//验证器类方法
public function messages()
{
    return [
        'username.required'     => '用户名不得为空',
        'username.min'          => '用户名不得小于2 位',
        'username.max'          => '用户名不得大于10 位',
        'password.required'     => '密码不得为空',
        'password.min'          => '密码不得小于6 位',
    ];
}

6、也可以自定义属性名,而其它采用默认提示;在验证类创建attributes()修改实现:

public function attributes()
{
    return [
        'username' => '用户名',
    ];
}

PS:提示语言包在:resources\lang\en\validation.php

7、每次都要自己修改验证类的提示,实属麻烦,可以直接下载官网的中文语言包。

官网资源地址:https://github.com/Laravel-Lang/lang 下载后,将zh_CN 这个文件,放在 resources\lang 目录下, 然后修改 config/app.php 中的 'locale' => 'zh_CN' 即可。 然后,其他的提示,可根据实际情况调整修改。

19.3 手动验证的实现

手动验证,和第一节快速验证是一样的,都是在控制器验证;只不过,快速验证是全自动化的,无法局部控制更多的细节。 而手动验证,可以实现更多的局部细节。

1、首先在控制类的具体方法中,创建手动验证,方法如下:

//手动创建验证器
$validator = Validator::make($request->post(), [
    'username' => 'required|min:2|max:10',
    'password' => 'required|min:6',
]);

这里注意: Validator是Illuminate\Support\Facades\Validator; make方法传入的两个参数,第一个是Request请求的数据,第二个是具体的验证规则数组。

2、然后在控制类中,使用 $validatorfails() 方法,可以对验证的成败进行判断,如下:

//如果没有通过的话
if ($validator->fails()) {
    //跳转后,并将错误保存,还可以返回上一次填的信息
    return redirect('/task/form')->withErrors($validator)->withInput();
    //  redirect:跳转;
    //  withErrors:带上错误信息;
    //  withInput:带上输入的表单旧数据。
}

3、如果同一个页面有多个表单,可以设置 $errors 的多个错误包,有两种方法定义:

一种是,在创建手动验证的时候,定义:

$validator = Validator::make($request->post(), [
    'username' => 'required|min:2|max:10',
    'password' => 'required|min:6',
])->validateWithBag('a'); //设置快速验证和手动验证,针对a表单。

另一种是,页面跳转的时候,定义:

if ($validator->fails()) {
    //跳转后,并将错误保存,还可以返回上一次填的信息
    return redirect('/task/form')->withErrors($validator, 'a')->withInput();
    //  redirect:跳转;
    //  withErrors:带上错误信息;其中的参数表示此验证是针对a表单的;
    //  withInput:带上输入的表单旧数据。
}

然后,在前端,使用如下方法显示错误信息:

@if ($errors->a->any())
    <div>
        <ul>
            @foreach ($errors->a->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

4、我们也可以在验证完毕之前,通过附加回调添加更多的自定义错误信息;

在控制类中,接着定义之后:

//验证钩子
$validator->after(function ($validator) {
    //判断你要判断的内容
    $validator->errors()->add('info', '隐藏字段info 的值不存在');
});

5、关于 $errors 对象,除了 any() 判断, all() 获取全部,还有一些别的方法;

{{--获取指定字段第一条信息--}}
{{$errors->first('username')}}

{{--判断指定字段是否有错误信息--}}
{{$errors->has('username')}}

19.4 验证规则大全

验证规则,提供了大量实用封装好的规则,我们只需要进行调用即可; 完整的验证规则,详见:https://learnku.com/docs/laravel/7.x/validation/7467#available-validation-rules 19. 表单与验证 - 图1

前面,我们使用了 requiredminmax 这三种比较简单的;下面,挑出比较典型常用的。

1、alpha_dash:字段必须由字母、数字破折号(-)和下划线(_)构成;

'username' => 'required|alpha_dash',

2、between:字段长度必须在指定的区间之间

'username' => 'required|between:2,6',

3、size:字段长度固定在某个值

'username' => 'required|size:6',

4、email:字段必须符合email 格式;

'username' => 'required|email',

5、unique:users:字段值是唯一的,通过指定数据表字段检查;

'username' => 'required|unique:users',

6、confiremed:这个基本用于密码和密码确认,固定了字段名称;

'password' => 'required|min:6|confirmed',

<input type="password" name="password_confirmation">

7、different:password:字段和另一个字段不可以相同的验证;

'username' => 'required|different:password',//即username不能和password相同。

8、ip / json:字段是否是ip 地址/字段是否是json 数据;

'username' => 'required|ip',
'username' => 'required|json',

还有一些其他格式的用法,如下:

9、验证方法还提供了 Rule 类 提供更加流程的验证构造,比如 innot_in

///username只能从指定的范围取值:
'username' => 'required|in:tom,jack,lusy',

//推荐下面这种
'username' => [
    'required',
    Rule::in(['tom', 'jack', 'lusy'])
],

//如果只验证一个规则,不需要数组,如果规则名有下划线,首字母大写
'username' => Rule::notIn(['tom', 'jack', 'lusy']),

10、Rule 类还可以结合 where来限制验证范围等操作;

//验证是否重复
'username' => Rule::unique('users'),
'username' => Rule::unique('users')->where(function ($query) {
    $query->where('id', 20);
}),

以上。