Laravel 验证类 实现 路由场景验证 和 控制器场景验证
基于不破坏框架原本用法、方便、简单的原则,实现路由场景验证和控制器场景验证。
第一步
创建 app\Http\Requests\SceneValidator.php
trait
<?php
namespace App\Http\Requests;
trait SceneValidator
{
//场景
protected $scene = null;
//是否自动验证
protected $autoValidate = true;
protected $onlyRule=[];
/**
* 覆盖 ValidatesWhenResolvedTrait 下 validateResolved 自动验证
*/
public function validateResolved()
{
if(method_exists($this,'autoValidate')){
$this->autoValidate = $this->container->call([$this, 'autoValidate']);
}
if ($this->autoValidate) {
$this->handleValidate();
}
}
/**
* 复制 ValidatesWhenResolvedTrait -> validateResolved 自动验证
*/
protected function handleValidate()
{
$this->prepareForValidation();
if (! $this->passesAuthorization()) {
$this->failedAuthorization();
}
$instance = $this->getValidatorInstance();
if ($instance->fails()) {
$this->failedValidation($instance);
}
}
/**
* 定义 getValidatorInstance 下 validator 验证器
* @param $factory
* @return mixed
*/
public function validator($factory)
{
return $factory->make($this->validationData(), $this->getRules(), $this->messages(), $this->attributes());
}
/**
* 验证方法(关闭自动验证时控制器调用)
* @param string $scene 场景名称 或 验证规则
*/
public function validate($scene='')
{
if(!$this->autoValidate){
if(is_array($scene)){
$this->onlyRule = $scene;
}else{
$this->scene = $scene;
}
$this->handleValidate();
}
}
/**
* 获取 rules
* @return array
*/
protected function getRules()
{
return $this->handleScene($this->container->call([$this, 'rules']));
}
/**
* 场景验证
* @param array $rule
* @return array
*/
protected function handleScene(array $rule)
{
if($this->onlyRule){
return $this->handleRule($this->onlyRule,$rule);
}
$sceneName = $this->getSceneName();
if($sceneName && method_exists($this,'scene')){
$scene = $this->container->call([$this, 'scene']);
if(array_key_exists($sceneName,$scene)) {
return $this->handleRule($scene[$sceneName],$rule);
}
}
return $rule;
}
/**
* 处理Rule
* @param $sceneRule
* @param $rule
* @return array
*/
private function handleRule(array $sceneRule,array $rule)
{
$rules = [];
foreach ($sceneRule as $key => $value) {
if (is_numeric($key) && array_key_exists($value,$rule)) {
$rules[$value] = $rule[$value];
} else {
$rules[$key] = $value;
}
}
return $rules;
}
/**
* 获取场景名称
*
* @return string
*/
protected function getSceneName()
{
return is_null($this->scene) ? $this->route()->getAction('_scene') : $this->scene;
}
}
第二步
在 app\Providers\AppServiceProvider.php
boot 方法里面添加
use Illuminate\Routing\Route;
//Route 路由自定义scene(场景方法)
Route::macro('scene',function ($scene=null){
$action = Route::getAction();
$action['_scene'] = $scene;
Route::setAction($action);
});
该自定义方法用于路由场景验证,在 Route->action
增加一个 _scene
属性;用法跟 路由别名 name
一样:
Route::post('add','UserController@add')->scene('add');
Tip:如果不需要路由场景验证,则不用添加。
用法
在验证类内里 use SceneValidator
;
例如下面 UserRequest 验证类
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
use SceneValidator;
/**
* 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 [
'name' => 'required|string|unique:users',
'email' => 'required|email|unique:users',
];
}
/**
* 场景规则
* @return array
*/
public function scene()
{
return [
//add 场景
'add' => [
'name' , //复用 rules() 下 name 规则
'email' => 'email|unique:users' //重置规则
],
//edit场景
'edit' => ['name'],
];
}
}
场景规则
在验证类里面添加scene
方法
/**
* 场景规则
* @return array
*/
public function scene()
{
// 格式 ['场景名' => [规则]]
return [
//add 场景
'add' => [
'name', //复用 rules() 下 name 规则
'email' => 'email|unique:users' //重置规则
],
//edit场景
'edit' => ['name'],
];
}
自动验证控制
在验证类里面添加 autoValidate
方法来控制自动验证; true:开启 | false:关闭
默认开启。
/**
* 设置是否自动验证
* @return bool
*/
public function autoValidate(){
return false; //关闭
}
可以根据不同需求开启和关闭灵活控制(此处要配合路由场景验证有效;控制器场景验证则必须关闭自动验证);比如某些场景下关闭
public function autoValidate(){
$sceneName = $this->getSceneName();
if(in_array($sceneName,['add'])){ //add 场景下关闭自动验证
return false;
}
}
路由场景验证
Route::post('create','UserController@create');
Route::post('add','TestController@add')->scene('add');
控制器场景验证
Tip:控制器场景验证需要 关闭自动验证 ,通过
validate('场景名')
来调起验证;优先级: 控制器场景验证 > 路由场景验证
public function add(UserRequest $request){
$request->validate('add');
}
支持全部验证 、独立验证规则
//全部验证 rules()下规则
$request->validate();
// 独立传验证规则
$request->validate( [
'name', //复用 rules() 下 name 规则
'email' => 'email|unique:users' //重置规则
]);
一直没有找到自己理想的场景验证,于是整理了这套场景验证,供参考;
如有更好的场景验证,求分享学习下;
由于第一次写有不足的地方,请各位谅解!
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: