站长资讯网
最全最丰富的资讯网站

教你修改Laravel FormRequest验证,实现场景验证

下面由Laravel教程栏目给大家介绍修改Laravel FormRequest验证,实现场景验证,希望对需要的朋友有所帮助!

教你修改Laravel FormRequest验证,实现场景验证

在Laravel 中,很多创建和编辑的的接口都是需要做数据验证的,对于数据验证一般有2种方方式

  • 在控制器里直接使用Request的validate方法

  • 使用自定义FormRequest类,该类集成自HttpRequest

    如果使用第一种方法,会比较乱,看起来不够优雅

    但是如果使用第二种方式,那么针对每一种请求都要定义一个FormRequest

    比如:ArticleStoreRequestArticleUpdateRequest

    但是你会发现基本上验证规则是一样的,当然你可以在控制器方法里只注入一个Request,但是如果针对于一个Model 有多个Update的那种,比如用户模块,修改密码/修改昵称/修改头像/修改地址/修改。。。怎么处理呢

    所以这几天针对这种情况,改进了下Laravel的Request机制,加了一个场景验证

    • 第一步:先创建一个AbstractRequest的基类
    <?php  namespace AppHttpRequests;  use IlluminateFoundationHttpFormRequest; use IlluminateSupportStr;  /**  * 使用方法:  * Class AbstractRequest  * @package AppHttpRequests  */ class AbstractRequest extends FormRequest {     public $scenes = [];     public $currentScene;               //当前场景     public $autoValidate = false;       //是否注入之后自动验证     public $extendRules;      public function authorize()     {         return true;     }      /**      * 设置场景      * @param $scene      * @return $this      */     public function scene($scene)     {         $this->currentScene = $scene;         return $this;     }      /**      * 使用扩展rule      * @param string $name      * @return AbstractRequest      */     public function with($name = '')     {         if (is_array($name)) {             $this->extendRules = array_merge($this->extendRules[], array_map(function ($v) {                 return Str::camel($v);             }, $name));         } else if (is_string($name)) {             $this->extendRules[] = Str::camel($name);         }          return $this;     }      /**      * 覆盖自动验证方法      */     public function validateResolved()     {         if ($this->autoValidate) {             $this->handleValidate();         }     }      /**      * 验证方法      * @param string $scene      * @throws IlluminateAuthAccessAuthorizationException      * @throws IlluminateValidationValidationException      */     public function validate($scene = '')     {         if ($scene) {             $this->currentScene = $scene;         }         $this->handleValidate();     }      /**      * 根据场景获取规则      * @return array|mixed      */     public function 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      */     public function validator($factory)     {         return $factory->make(             $this->validationData(), $this->getRules(),             $this->messages(), $this->attributes()         );     }      /**      * 最终验证方法      * @throws IlluminateAuthAccessAuthorizationException      * @throws IlluminateValidationValidationException      */     protected function handleValidate()     {         if (!$this->passesAuthorization()) {             $this->failedAuthorization();         }         $instance = $this->getValidatorInstance();         if ($instance->fails()) {             $this->failedValidation($instance);         }     }  }
    • 第二步:针对用户Request,我们只需要定义一个UserRequest继承AbstractRequest
    <?php  namespace AppHttpRequests;  class UserRequest extends AbstractRequest {   public $scenes = [       'nickname' => 'nickname',       'avatar' => 'avatar',       'password' => 'password',       'address' => 'province_id,city_id'   ];    public function rules()   {       return [        //全部的验证规则           'mobile' => [],           'nickname' => [],           'password' => [               'required', 'min:6', 'max:16'           ],           'avatar' => [],           'province_id' => [],           'city_id' => [],           //...       ];   }    public function passwordRules()   {       return [           'password' => [               'required', 'min:6', 'max:16', 'different:$old_password'      //修改新密码不和旧密码相同,此处只是举例子,因为密码需要Hash处理才能判断是否相同           ]       ];   } }
    • 控制器方法 UserController
    <?php  namespace AppHttpControllers;  use AppHttpRequestsUserRequest;  class UserController {      public function register(UserRequest $request)     {         $request->validate();   //默认不设置场景 全部验证         //...     }      public function updateAddress($id, UserRequest $request)     {         $request->scene('address')->validate();         //...     }      public function updateAvatar($id, UserRequest $request)     {         $request->validate('avatar');         //...     }      public function updatePassword($id, UserRequest $request)     {         //设置password场景,只验证password字段,并且使用新的password规则替换原来的password规则         $request->scene('password')             ->with('password')             ->validate();         //...     } }

    该方法没有修改Laravel的核心验证逻辑,只让在FormRequest在注入到Controller的时候不要做自动验证,当然,如果需要自动验证,那么设置$autoValidate = true即可。

    以上内容仅供参考。望轻喷。

    同时还有我也修改了ORM的场景验证规则,可以在model里设置经常,同时满足多场景创建和更新

赞(0)
分享到: 更多 (0)
网站地图   沪ICP备18035694号-2    沪公网安备31011702889846号