Laravel 验证器以及验证场景的使用
Laravel 验证器以及验证场景的使用让你代码看起来更简洁
首先我们来看看传统写法
$data = $request->input();
$validator = Validator::make(
$data,
[
'account' => 'required:exists:admin_user',
'password' => 'required',
],
[
'account.required' => '账号不能为空',
'account.exists' => '账号或密码错误',
'password' => '密码不能为空'
]
);
$vali = $validator->fails();
if($vali) return $this->backData(0,'err',$validator->getMessageBag()->first());
这样的写法容易造成代码冗余太多。
下面我们提供一种简单的方法
1、首先创建一个基础类
#创建一个BaseRequest类
php artisan make:request BaseRequest
#类里面的内容
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
class BaseRequest extends FormRequest
{
#验证没有通过证失败后返回结果
protected function failedValidation(Validator $validator) {
$msg = $validator->getMessageBag()->first();
throw new HttpResponseException(response()->json(['code'=>'500','msg'=>$msg,'data'=>''], 422));
}
}
2、在 app\Providers\AppServiceProvider.php boot 下面添加
//Route 路由自定义scene(场景方法)
Route::macro('scene',function ($scene=null){
$action = Route::getAction();
$action['_scene'] = $scene;
Route::setAction($action);
});
3、创建一个验证类
<?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;
}
}
4、创建自己的验证类 代码如下
<?php
namespace App\Http\Requests;
class StorePostRequest extends BaseRequest
{
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 [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
/**
* 获取已定义验证规则的错误消息。
*
* @return array
*/
public function messages()
{
return [
'title.required' => 'A title is required',
'body.required' => 'A message is required',
];
}
/**
* 场景规则
* @return array
*/
public function scene()
{
return [
//add 场景
'add' => [
'title' , //复用 rules() 下 name 规则
'body'
],
//edit场景
'edit' => ['body'],
];
}
}
5、来看看我们路由是如何写的
#这里我们使用的验证场景是edit
Route::get('/posts/popular', [\App\Http\Controllers\PostController::class, 'popular'])->scene('edit');
6、我们只需要爸验证类注入到控制器就OK了
// 获取热门文章排行榜
public function popular(StorePostRequest $request)
{
$posts = $this->postRepo->trending(10);
if ($posts) {
dd($posts->toArray());
}
}
7、接下来看一下结果
页:
[1]