教你修改LaravelFormRequest验证,实现场景验证
                                            下面由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
     */
    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 \\Illuminate\\Auth\\Access\\AuthorizationException
     * @throws \\Illuminate\\Validation\\ValidationException
     */
    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 \\Illuminate\\Auth\\Access\\AuthorizationException
     * @throws \\Illuminate\\Validation\\ValidationException
     */
    protected function 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'
  ];
  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处理才能判断是否相同
          ]
      ];
  }
}控制器方法 UserControllervalidate();   //默认不设置场景 全部验证
        //...
    }
    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里设置经常,同时满足多场景创建和更新
新闻名称:教你修改LaravelFormRequest验证,实现场景验证
转载来于:http://www.scyingshan.cn/article/cgjppo.html

 建站
建站
 咨询
咨询 售后
售后
 建站咨询
建站咨询 
 