这篇文章将为大家详细讲解有关如何修改Laravel FormRequest验证实现场景验证,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
在Laravel 中,很多创建和编辑的的接口都是需要做数据验证的,对于数据验证一般有2种方方式
在控制器里直接使用Request的validate方法
使用自定义FormRequest类,该类集成自Http\Request
如果使用第一种方法,会比较乱,看起来不够优雅
但是如果使用第二种方式,那么针对每一种请求都要定义一个FormRequest
比如:ArticleStoreRequest和ArticleUpdateRequest
但是你会发现基本上验证规则是一样的,当然你可以在控制器方法里只注入一个Request,但是如果针对于一个Model 有多个Update的那种,比如用户模块,修改密码/修改昵称/修改头像/修改地址/修改。。。怎么处理呢
所以这几天针对这种情况,改进了下Laravel的Request机制,加了一个场景验证
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Str;
/**
* 使用方法:
* Class AbstractRequest
* @package App\Http\Requests
*/
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 \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);
}
}
}
<?php
namespace App\Http\Requests;
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处理才能判断是否相同
]
];
}
}
<?php
namespace App\Http\Controllers;
use App\Http\Requests\UserRequest;
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里设置经常,同时满足多场景创建和更新
控制器方法 UserController
第二步:针对用户Request,我们只需要定义一个UserRequest继承AbstractRequest
第一步:先创建一个AbstractRequest的基类
关于“如何修改Laravel FormRequest验证实现场景验证”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。