Laravel 5x 自定义数据验证

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 了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容

  • 1、简介 Laravel 提供了多种方法来验证应用输入数据。默认情况下,Laravel 的控制器基类使用Valid...
    伊Summer阅读 1,519评论 0 4
  • 原文链接 必备品 文档:Documentation API:API Reference 视频:Laracasts ...
    layjoy阅读 8,597评论 0 121
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 验证 简介 Laravel 对验证应用的输入数据提供了多中途径的实现。默认的,Laravel 的基础控制器类使用了...
    Dearmadman阅读 10,189评论 5 8
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,280评论 25 707