美文网首页
Laravel 5x 自定义数据验证

Laravel 5x 自定义数据验证

作者: kylesean | 来源:发表于2017-01-09 23:16 被阅读1250次

    Laravel本身内置了许多好用的数据校验规则,拿来即用,但这远远不够,我们需要自定义自己的验证规则是必要的,先看一个简单的示例:

    简单验证

    直接在 app\Providers\AppServiceProvider.php 里扩展 Validator

    打开 app\Providers\AppServiceProvider.php ,在 boot()方法里添加我们自己的验证规则,比方说我们需要一个验证是祖国的手机号码(+86):

    namespace App\Providers;
     
    use Illuminate\Support\ServiceProvider;
    use Validator;
     
    class AppServiceProvider extends ServiceProvider
    {
     
        public function boot()
        {
            Validator::extend('cn_phone', function($attribute, $value, $parameters) {
                return substr($value, 0, 3) == '+86';
            });
        }
     
    }
    
    

    参考文档我们发现,自定义验证器闭包接收四个参数,分别是要验证的属性名称、属性值、传递给规则的参数数组以及 Validator 实例。

    这里:cn_phone 是我们将在验证请求类中使用的规则名称,验证通过返回 TRUE , 失败返回 FALSE,参数 $attribute 是要验证的字段的名称,参数 $parameters 用于更复杂的验证规则,像 Laravel 中默认存在的 min:xsame:field 这种。

    下面演示:
    定义一个 /form_store 路由指向 FormControllerpostForm 方法,再定义个请求类 CreateUserRequest 依赖注入。

    public function postForm(CreateUserRequest $request)
    {
        return "Success!";
    }
    
    

    app\Http\Requests\CreateUserRequest.php

    <?php 
    namespace App\Http\Requests;
     
    class CreateUserRequest extends Request {
     
        /**
         * Determine if the user is authorized to make this request.
         *
         * @return bool
         */
        public function authorize()
        {
            return true;
        }
     
        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {
            return [
                'phone' => 'required|cn_phone',
            ];
        }
    }
    

    我就用自带的 welcome.blade.php 模板页面给大家演示一下:

    <div class="content">
        <div class=title m-b-md>
            @if(count($errors) > 0)
                @foreach($errors->all() as $error)
                    <li>{{ $error }}</li>  
                @endforeach
            @endif
            <form action="{{ url('form_store') }}" method="post">
                {{ csrf_field() }}
                <input type="text" name="phone">
                <input type="submit" value="确认">
            </form>
        </div>
    </div>
    
    

    preview:

    image

    好像出错提示出来了,有木有,但是这不是我们想要的,我们要自定义一个错误消息。打开 resources/lang/en/validation.php 找到

    'custom' => [
            'attribute-name' => [
                'rule-name' => 'custom-message',
            ],
        ],
    

    按照此格式要求,改写成我们定义的验证字段和对应的返回错误消息提示:

    'custom' => [
            'phone' => [
                'zn_phone' => '请加手机号的国际区号+86',
            ],
        ],
    
    

    再次验证:


    image

    这还远远不够,对于复杂的数据验证呢?

    复杂验证

    自定义的 Validator
    假设有这么个验证要求,是 phoneemail 当输入手机号时,邮箱就不能同时输入(什么奇葩需求),来看如何定义自己的验证类:

    首先我们想到的是这个自定义验证类放哪里好呢?这里我个人建议在 app 下新建一个目录,我取名为 Librarys ,这里放一些公共函数库,第三方支付模块以及我们的自定义验证类等等。上代码:

    app\Providers\MyValidator.php

    <?php 
    namespace App\Librarys;
     
    use Illuminate\Validation\Validator;
     
    class MyValidator extends Validator {
     
        public function validateEmptyWith($attribute, $value, $parameters)
        {
            return ($value != '' && $this->getValue($parameters[0]) != '') ? false : true;
        }
    }
    

    App\Providers\AppServiceProvider

    <?php
    
    namespace App\Providers;
    use Illuminate\Support\Facades\Validator;
    use Illuminate\Support\ServiceProvider;
    use App\Librarys;
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
    
            Validator::resolver(function($translator, $data, $rules, $messages)
            {
                return new MyValidator($translator, $data, $rules, $messages);
            });
        }
    
    

    resources\lang\en\validation.php

    'custom' => [
        'phone' => [
            'empty_with' => '只能填一个字段,不能同时',
        ],
    ],
    

    定义好验证类,这个类只是扩展了 Laravel的内置验证基类,想让我们的验证规则被 Laravel “承认”,必须进入 AppServiceProviderboot 方法启动载入。

    分析返回条件,想一想如果达不到上面的“需求”,那意味着:

    • 不输入手机号,输入邮箱
    • 不输入手机号,不输入邮箱
    • 两者都不输入

    满足这三个条件即为验证通过,那么取反后判断条件如上,大家不用纠结这个判断,着重看 $this->getValue($parameters[0]) 这个方法,参数数组 $parameters[0] 为对应第一个验证规则,类似 min:xxx, 这里是 empty_with:email,通过该参数获取 email 对应的值传入 getValue() 中再返回 bool 值。问题来了,为什么是 empty_with:email 不是 emptyWith:email 或其他的呢,其实框架内部已经为我们处理好了名称的对应的格式,我们自定义的验证类里的验证方法必须以 validate 开头然后接小驼峰命名,对应验证规则的名称就是下划线的方式。这点要牢记

    效果图就不放了,大家可以尝试下,这样,基本上我们单独自定义的验证类结构就比较清晰了,利用面向对象的方式抽离出独立的验证类,更符合单一职责原则,这里其实还可以优化,比如独立出一个 ValidationExtensionServiceProvider extends ServiceProvider:

    class ValidationExtensionServiceProvider extends ServiceProvider
    {
    
        public function register() {}
    
        public function boot()
        {
            $this->app->validator->resolver( function( $translator, $data, $rules, $messages = array(), $customAttributes = array() ) {
                return new ValidatorExtended( $translator, $data, $rules, $messages, $customAttributes );
            } );
        }
    }   
    

    然后告诉 laravel 载入该服务,app/config/app.php 里添加进去。这样就更符合 Laravel Way 了。

    相关文章

      网友评论

          本文标题:Laravel 5x 自定义数据验证

          本文链接:https://www.haomeiwen.com/subject/iftkbttx.html