下面由Laravel教程栏目给大家介绍修改Laravel FormRequest验证,实现场景验证,希望对需要的朋友有所帮助!
在Laravel 中,很多创建和编辑的的接口都是需要做数据验证的,对于数据验证一般有2种方方式
在控制器里直接使用Request的validate方法
使用自定义FormRequest类,该类集成自Http\\\\Request
如果使用第一种方法,会比较乱,看起来不够优雅
但是如果使用第二种方式,那么针对每一种请求都要定义一个FormRequest
比如:ArticleStoreRequest和ArticleUpdateRequest
但是你会发现基本上验证规则是一样的,当然你可以在控制器方法里只注入一个Request,但是如果针对于一个Model 有多个Update的那种,比如用户模块,修改密码/修改昵称/修改头像/修改地址/修改。。。怎么处理呢
所以这几天针对这种情况,改进了下Laravel的Request机制,加了一个场景验证
第一步:先创建一个AbstractRequest的基类
复制currentScene = $scene;return $this;}/**
* 使用扩展rule
* @param string $name
* @return AbstractRequest
*/publicfunctionwith($name =){if(is_array($name)){
$this->extendRules = array_merge($this->extendRules[], array_map(function($v){returnStr::camel($v);}, $name));}elseif(is_string($name)){
$this->extendRules[]=Str::camel($name);}return $this;}/**
* 覆盖自动验证方法
*/publicfunction validateResolved(){if($this->autoValidate){
$this->handleValidate();}}/**
* 验证方法
* @param string $scene
* @throws \\\\Illuminate\\\\Auth\\\\Access\\\\AuthorizationException
* @throws \\\\Illuminate\\\\Validation\\\\ValidationException
*/publicfunction validate($scene =){if($scene){
$this->currentScene = $scene;}
$this->handleValidate();}/**
* 根据场景获取规则
* @return array|mixed
*/publicfunction getRules(){
$rules = $this->container->call([$this,rules]);
$newRules =[];if($this->extendRules){
$extendRules = array_reverse($this->extendRules);foreach($extendRules as $extendRule){if(method_exists($this,"{$extendRule}Rules")){//合并场景规则
$rules = array_merge($rules, $this->container->call([$this,"{$extendRule}Rules"]));}}}if($this->currentScene && isset($this->scenes[$this->currentScene])){
$sceneFields = is_array($this->scenes[$this->currentScene])? $this->scenes[$this->currentScene]: explode(,, $this->scenes[$this->currentScene]);foreach($sceneFields as $field){if(array_key_exists($field, $rules)){
$newRules[$field]= $rules[$field];}}return $newRules;}return $rules;}/**
* 覆盖设置 自定义验证器
* @param $factory
* @return mixed
*/publicfunction validator($factory){return $factory->make(
$this->validationData(), $this->getRules(),
$this->messages(), $this->attributes());}/**
* 最终验证方法
* @throws \\\\Illuminate\\\\Auth\\\\Access\\\\AuthorizationException
* @throws \\\\Illuminate\\\\Validation\\\\ValidationException
*/protectedfunction handleValidate(){if(!$this->passesAuthorization()){
$this->failedAuthorization();}
$instance = $this->getValidatorInstance();if($instance->fails()){
$this->failedValidation($instance);}}}
第二步:针对用户Request,我们只需要定义一个UserRequest继承AbstractRequest
复制nickname,avatar=>avatar,password=>password,address=>province_id,city_id];publicfunction rules(){return[//全部的验证规则mobile=>[],nickname=>[],password=>[required,min:6,max:16],avatar=>[],province_id=>[],city_id=>[],//...];}publicfunction passwordRules(){return[password=>[required,min:6,max:16,different:$old_password//修改新密码不和旧密码相同,此处只是举例子,因为密码需要Hash处理才能判断是否相同]];}}
控制器方法 UserController
复制validate();//默认不设置场景 全部验证//...}publicfunction updateAddress($id,UserRequest $request){
$request->scene(address)->validate();//...}publicfunction updateAvatar($id,UserRequest $request){
$request->validate(avatar);//...}publicfunction updatePassword($id,UserRequest $request){//设置password场景,只验证password字段,并且使用新的password规则替换原来的password规则
$request->scene(password)->with(password)->validate();//...}}
该方法没有修改Laravel的核心验证逻辑,只让在FormRequest在注入到Controller的时候不要做自动验证,当然,如果需要自动验证,那么设置$autoValidate = true即可。
以上内容仅供参考。望轻喷。
同时还有我也修改了ORM的场景验证规则,可以在model里设置经常,同时满足多场景创建和更新