laravel有自己的几种参数校验实现,下面是我自己封装的,参照aop思想将参数校验集合到中间件中的实现过程。
# ./app/Validator/BaseValidator.php
namespace App\Validator;
use App\Exceptions\DevException;
use Illuminate\Http\Request;
abstract class BaseValidator
{
/**
* 当前访问路由
* @var
*/
protected $uri;
/**
* 验证器规则,key=>value,key为访问的路由,value为参数对应规则
* @var array
*/
protected $rules = [];
protected $message = [];
protected $attributes = [];
protected $customRules = [];
protected $request = null;
public function __construct(string $uri, Request $request) {
$this->uri = $uri;
$this->request = $request;
$this->makeCustomRules($this->request);
}
/**
* 自定义规则在此地方注册
* @param $request
*/
abstract protected function makeCustomRules($request): void ;
/**
* 通过自定义规则名称获取验证函数
* @param string $rule
* @return callable
* @throws DevException
*/
protected function getCustomRules(string $rule): callable {
if (!isset($this->customRules[$rule])) {
throw new DevException(['msg' => "验证器自定义规则错误"]);
}
return $this->customRules[$rule];
}
/**
* 设置自定义的验证规则
* @param string $rule 规则名称
* @param callable $ruleCall 规则验证回调函数
* @throws DevException
*/
protected function setCustomRules(string $rule, callable $ruleCall): void {
if (isset($this->customRules[$rule])) {
throw new DevException(['msg' => "验证器自定义规则重复了"]);
}
$this->customRules[$rule] = $ruleCall;
}
/**
* 通用自定义规则:检查添加的某个字段是否已存在
* @param $model
* @param string $name
* @throws DevException
*/
protected function checkAddRepeat($model, $name="name") {
$strName = ucwords($name);//将首字母字段转为大写,可以根据业务更换为转为驼峰命名
$this->setCustomRules("checkAdd{$strName}Repeat", function ($attribute, $value, $fail)
use ($model, $name) {
if ($model::getOne([$name => $value])) {
$fail($value.' 已存在。');
}
});
}
/**
* 通用自定义规则:检查编辑的某个字段是否已存在
* @param $model
* @param string $name
* @throws DevException
*/
protected function checkEditRepeat($model, $name="name") {
$request = $this->request;
$strName = ucwords($name);//将首字母字段转为大写,可以根据业务更换为转为驼峰命名
$this->setCustomRules("checkEdit{$strName}Repeat", function ($attribute, $value, $fail)
use ($model, $name, $request) {
//根据字段+ID组合判断,可以根据具体业务修改
if ($model::getOne([$name => $value, "id" => ["<>", $request->id]])) {
$fail($value.' 已存在。');
}
});
}
/**
* 获取规则
* @return array
*/
public function getRules() : array {
if (isset($this->rules[$this->uri])) {
return $this->rules[$this->uri];
}
return [];
}
/**
* 获取自定义验证提示
* @return array
*/
public function getMessage() : array {
return $this->message;
}
/**
* 获取自定义属性描述
* @return array
*/
public function getCustomAttributes() : array {
return $this->attributes;
}
}
# ./app/Validator/AdminValidator.php
namespace App\Validator;
use App\Models\Admin;
use Illuminate\Http\Request;
class AdminValidator extends BaseValidator
{
protected $attributes = [
'name' => '用户名',
'password' => '密码',
'description' => '描述',
'selectRoles' => '绑定角色',
];
protected $message = [
'required' => ':attribute 为必填项',
];
public function __construct(string $uri, Request $request)
{
parent::__construct($uri, $request);
//rules数组key值匹配到路由URL将直接生效验证
$this->rules = [
//获取管理员列表
"admin/admins/getAdmins" => [
'page' => 'required|Integer|min:1',
'pageSize' => 'required|Integer|min:1',
],
//添加管理员
"admin/admins/add" => [
'name' => [
'required',
'max:255',
$this->getCustomRules("checkAddNameRepeat")
],
'description' => "required|String|min:6",
],
//编辑管理员
"admin/admins/edit" => [
'name' => [
'required',
'max:255',
$this->getCustomRules("checkEditNameRepeat")
],
'description' => "required|String|min:6",
],
//删除管理员
"admin/admins/del" => [
'id' => [
"required",
'Integer',
'min:1',
$this->getCustomRules("checkIsSuper"),
]
],
];
}
/**
* 自定义规则
* @param $request
* @throws \App\Exceptions\DevException
*/
protected function makeCustomRules($request): void
{
//检查添加名称是否存在
$this->checkAddRepeat(Admin::class);
//检查编辑的名称是否存在
$this->checkEditRepeat(Admin::class);
//检查删除的角色是否为超级管理员
$this->setCustomRules("checkIsSuper", function ($attribute, $value, $fail) {
if ($value === 1) {
$fail('该用户为超级管理权限,不能删除!');
}
});
}
}
# ./app/Http/Middleware/ParamsValidation.php
namespace App\Http\Middleware;
use App\Exceptions\DevException;
use App\Exceptions\ValidationException;
use Closure;
use Illuminate\Support\Facades\Validator;
class ParamsValidation
{
/**
* 校验前端传递参数是否合法
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param $Rules String 验证器对象名,AuthValidator验证器则传递Auth字段
* @return mixed
* @throws DevException
* @throws ValidationException
*/
public function handle($request, Closure $next, $Rules)
{
//验证器实现类
$RulesClass = "\App\Validator\\{$Rules}Validator";
if (!class_exists($RulesClass)) {
throw new DevException();
}
$rules = new $RulesClass($request->route()->uri, $request);
$validator = Validator::make(
$request->input(),
$rules->getRules(),
$rules->getMessage(),
$rules->getCustomAttributes()
);
if ($validator->fails()) {
$messages = $validator->getMessageBag()->getMessages();
$message = current($messages);
if (is_array($messages)) {
$message = current($message);
}
throw new ValidationException([
'msg' => $message
]);
}
return $next($request);
}
}
# ./app/Http/Kernel.php
protected $routeMiddleware = [
...
//表单参数验证
'validator' => \App\Http\Middleware\ParamsValidation::class,
];
# ./routes/web.php
// Admin 模块
Route::middleware('api.auth')->namespace('Admin')->prefix('admin')->group(function () {
//中间件validator传递参数Admin,标识匹配验证器./app/Validator/AdminValidator.php
Route::middleware('validator:Admin')->prefix('/admins')->group(function () {
// 获取管理员列表
Route::get('getAdmins', 'AdminController@getAdmins');
//添加管理员
Route::post('add', 'AdminController@add');
//编辑管理员
Route::put('edit', 'AdminController@edit');
//删除管理员
Route::delete('del', 'AdminController@del');
});
});
ReactAdmin-Laravel