今天在用thinkphp8写东西的时候发现,写验证器规则和场景优点费时间,就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。
就突发奇想能不能自动生成验证器,也不能是说自动生成验证器,生成验证其的话还是要生成相关的文件,这块因为没弄过就略过
就是说能写一个公共的动态验证器 然后规则场景啥的手动输入表名,场景规则和需要使用的场景。经过我小半天的尝试,初见成效,话不多说 上代码
包含rule(规则) message(提示信息) scene(场景)
代码示例
namespace app\services;
use think\Validate;
class AdminValidatee extends Validate
{
/**
* 定义验证规则
* 格式:'字段名' => ['规则1','规则2'...]
*
* @var array
*/
protected $rule = [];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [];
}
代码示例
namespace app\services;
use think\Validate;
class AdminValidatee extends Validate
{
/**
* 定义验证规则
* 格式:'字段名' => ['规则1','规则2'...]
*
* @var array
*/
protected $rule = [];
/**
* 定义错误信息
* 格式:'字段名.规则名' => '错误信息'
*
* @var array
*/
protected $message = [];
/**
* 定义验证场景
* 格式:'场景名' => ["字段1","字段2"]
*
* @var array
*/
protected $scene= [];
}
用户动态获取表的结构,包括字段,字段类型
代码示例:
// 获取表结构信息
$sql="SELECT COLUMN_NAME ,COLUMN_TYPE ,IS_NULLABLE ,COLUMN_DEFAULT ,COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = '$databaseName' AND TABLE_NAME ='$tableName'";
// 获取表结构信息
$columns = Db::query($sql);
$rules = [];
$messages = [];
foreach ($columns as $column) {
$field = $column['COLUMN_NAME'];//字段名
$fieldName = $column['COLUMN_COMMENT'];//注释
$type = $column['COLUMN_TYPE'];//字段类型
$isNullable = $column['IS_NULLABLE'] === 'YES' ? true : false;//是不是为null
// 根据字段类型和表结构自动生成验证规则
$rule = 'require';
// 如果字段允许为空,则移除 'require' 规则
if ($isNullable) {
$rule = 'nullable';
}
if (strpos($type, 'varchar') !== false || strpos($type, 'text') !== false) {
$rule .= '|length:1,255'; // 字符串类型添加长度验证
}
if (strpos($type, 'int') !== false) {
$rule .= '|number'; // 整数类型字段添加数字验证
}
// 针对 email 字段,增加邮箱格式验证
if ($field == 'email') {
$rule .= '|email';
}
// 添加到验证规则数组
$rules[$field] = $rule;
$messages[$field] = ucfirst($fieldName.$field) . ' is required and should be of valid format';
}
return ['rules' => $rules, 'messages' => $messages];
/**
* 验证
* User: MirGao
* Date: 2024/12/3
* Time: 14:58
* @param $param
* @param $scene
* @return void
*/
public function validate($param,$scene){
if(!self::scene($scene)->check($param)){
exit(json_encode(['code'=>'203','message'=>Validate::getError(),'data'=>[]]));
}
}
//参数为表名和验证场景
public function __construct($table,$sceneRule)
{
parent::__construct();
//通过表名动态获取表结构
$data=self::getValidate($table);
//赋值规则
$this->rule=$data['rules'];
//赋值提示信息
$this->message=$data['messages'];
//赋值验证场景
$this->scene=$sceneRule;
}
/**
* Notes:
* User: 14736
* Date: 2024/12/3
* Time: 13:46
* @return
*/
namespace app\services;
use think\facade\Db;
use think\Validate;
class ValidateService extends Validate
{
protected $rule = [];
protected $message = [];
protected $scene = [];
//参数为表名和验证场景
public function __construct($table,$sceneRule)
{
parent::__construct();
//通过表名动态获取表结构
$data=self::getValidate($table);
//赋值规则
$this->rule=$data['rules'];
//赋值提示信息
$this->message=$data['messages'];
//赋值验证场景
$this->scene=$sceneRule;
}
/**
* 获取表结构数据
* User: MirGao
* Date: 2024/12/3
* Time: 14:58
* @param $tableName 表名
* @return array[]
*/
static public function getValidate($tableName){
// 获取表结构信息
$sql="SELECT COLUMN_NAME ,COLUMN_TYPE ,IS_NULLABLE ,COLUMN_DEFAULT ,COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'questions' AND TABLE_NAME ='$tableName'";
// 获取表结构信息
$columns = Db::query($sql);
$rules = [];
$messages = [];
foreach ($columns as $column) {
$field = $column['COLUMN_NAME'];
$fieldName = $column['COLUMN_COMMENT'];
$type = $column['COLUMN_TYPE'];
$isNullable = $column['IS_NULLABLE'] === 'YES' ? true : false;
// 根据字段类型和表结构自动生成验证规则
$rule = 'require';
// 如果字段允许为空,则移除 'require' 规则
if ($isNullable) {
$rule = 'nullable';
}
if (strpos($type, 'varchar') !== false || strpos($type, 'text') !== false) {
$rule .= '|length:1,255'; // 字符串类型添加长度验证
}
if (strpos($type, 'int') !== false) {
$rule .= '|number'; // 整数类型字段添加数字验证
}
// 针对 email 字段,增加邮箱格式验证
if ($field == 'email') {
$rule .= '|email';
}
// 添加到验证规则数组
$rules[$field] = $rule;
$messages[$field] = ucfirst($fieldName.$field) . ' is required and should be of valid format';
}
return ['rules' => $rules, 'messages' => $messages];
}
/**
* 验证
* User: MirGao
* Date: 2024/12/3
* Time: 14:58
* @param $param
* @param $scene
* @return void
*/
public function validate($param,$scene){
if(!self::scene($scene)->check($param)){
exit(json_encode(['code'=>'203','message'=>Validate::getError(),'data'=>[]]));
}
}
}
<?php
/**
* Notes:
* User: 14736
* Date: 2024/12/3
* Time: 13:17
* @return
*/
namespace app\admin\controller;
use app\admin\model\AdminModel;
use app\admin\validate\AdminValidate;
use app\services\JsonResponse;
use app\services\JwtService;
use app\services\ValidateService;
use think\Request;
class LoginController
{
//定义验证场景
protected $sceneRule=[];
public function __construct(){
//根据业务进行添加场景
$this->sceneRule=[
'login'=>['admin_account','admin_password']
];
}
/**
* 登录
* User: MirGao
* Date: 2024/12/3
* Time: 15:04
* @param Request $request
* @param JwtService $jwtService
* @param AdminModel $adminModel
* @return \think\response\Json
*/
public function login(Request $request ,JwtService $jwtService,AdminModel $adminModel){
$param=$request->post();
//传入表名 验证场景
$validate=new ValidateService('system_admin',$this->sceneRule);
$validate->validate($param,'login');
$adminId='查询语句';
if(empty($adminId)){
return JsonResponse::error('用户不存在');
}
$token= $jwtService->getToken($adminId);
return JsonResponse::successData(['token'=>$token]);
}
}
1、写起来简便,完成一个公共验证文件后只需要传入 表明和验证场景并调用验证场景中的相关规则即可完成验证
2、无需关心表的结构变化
1、每次调用都会去查询数据库性能开销有点大
2、耦合性很高 所有的验证都走这一个方法调试时会比较差异化
3、要求开发者建表时要按照规范,写字段注释
针对于每次验证都需要查询表结构,建议上缓存,查询后把表结构放在缓存里,当表结构发生变化时需要及时更新缓存,如果有更好的想法欢迎交流