ThinkPHP场景动态验证
一、缘由
今天在用thinkphp8写东西的时候发现,写验证器规则和场景优点费时间,就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。
就突发奇想能不能自动生成验证器,也不能是说自动生成验证器,生成验证其的话还是要生成相关的文件,这块因为没弄过就略过
就是说能写一个公共的动态验证器 然后规则场景啥的手动输入表名,场景规则和需要使用的场景。经过我小半天的尝试,初见成效,话不多说 上代码
二、实现
实现步骤
1、创建正常的验证器的模式
包含rule(规则) message(提示信息) scene(场景)
代码示例
<?phpnamespace app\services;
use think\Validate;
class AdminValidatee extends Validate
{/*** 定义验证规则* 格式:'字段名' => ['规则1','规则2'...]** @var array*/protected $rule = [];/*** 定义错误信息* 格式:'字段名.规则名' => '错误信息'** @var array*/protected $message = [];
}
2、添加验证场景
代码示例
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= [];
}
3、创建一个获取表结构的方法
用户动态获取表的结构,包括字段,字段类型
代码示例:
// 获取表结构信息$sql="SELECT COLUMN_NAME ,COLUMN_TYPE ,IS_NULLABLE ,COLUMN_DEFAULT ,COLUMN_COMMENT FROM information_schema.COLUMNSWHERE 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];
4、创建验证方法
/*** 验证* 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'=>[]]));}}
5、接收实例化传过来的参数用构造函数进行赋值
//参数为表名和验证场景public function __construct($table,$sceneRule){parent::__construct();//通过表名动态获取表结构$data=self::getValidate($table);//赋值规则$this->rule=$data['rules'];//赋值提示信息$this->message=$data['messages'];//赋值验证场景$this->scene=$sceneRule;}
6、完整代码
<?php
/*** 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.COLUMNSWHERE 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、要求开发者建表时要按照规范,写字段注释
优化
针对于每次验证都需要查询表结构,建议上缓存,查询后把表结构放在缓存里,当表结构发生变化时需要及时更新缓存,如果有更好的想法欢迎交流
相关文章:

ThinkPHP场景动态验证
一、缘由 今天在用thinkphp8写东西的时候发现,写验证器规则和场景优点费时间,就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。 就突发奇想能不能自动生成验证器,也不能是说自动生成验证器,生成验证其的…...

在M3上面搭建一套lnmp环境
下载docker-desktop 官网下载docker-desktop 切换镜像源 {"builder": {"gc": {"defaultKeepStorage": "20GB","enabled": true}},"experimental": false,"registry-mirrors": ["https://docke…...

【C++笔记】二叉搜索树
前言 各位读者朋友们大家好!上期我们讲完了面向对象编程三大属性之一的多态,这一期我们再次开始数据结构二叉搜索树的讲解。 目录 前言一. 二叉搜索树的概念二. 二叉搜索树的性能分析三. 二叉搜索树的插入四. 二叉搜索树的查找五. 二叉搜索树的删除六.…...

Fork/Join框架简介
一、Fork/Join框架简介 Fork/Join框架是Java 7引入的一个用于并行执行任务的框架,它可以将一个大任务分割成若干个小任务,并行执行这些小任务,然后将每个小任务的结果合并起来,得到大任务的结果。这种框架特别适合于能够被递归分…...

Java项目实战II基于微信小程序的电子竞技信息交流平台的设计与实现(开发文档+数据库+源码)
目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的飞速发展…...

Mysql读写分离分库分表
读写分离 什么是读写分离 读写分离主要是为了将对数据库的读写操作分散到不同的数据库节点上。 这样的话,就能够小幅提升写性能,大幅提升读性能。一般情况下,我们都会选择一主多从,也就是一台主数据库负责写,其他的从…...

B站狂神说--springboot项目学习(新建一个springboot项目)
文章目录 1.新建项目java8项目1.解决自带的idea2024无法使用java8的问题 2.新建接口3.项目打包为jar包4.使用jar包 1.新建项目java8项目 1.解决自带的idea2024无法使用java8的问题 将server.url修改为阿里云的地址:https://start.aliyun.com/ 选择Spring Web 创建…...

eltable el-table 横向 滚动条常显
又遇到了难受的问题,el-table嵌入在一个div里面,结果因为内容太多,横向、纵向我都得滚动查看! 结果发现横向滚动时只能让它纵向触底后才能进行横向操作,这就很变态,明显不符合用户操作习惯。如下图: 要先纵…...

centos8 mysql 主从复制
原理 一、一主一从 准备工作 1.主库配置 1、修改配置文件 /etc/my.cnf #mysql 服务ID,保证整个集群环境中唯一,取值范围:1-232-1,默认为 server-id1 #是否只读,1 代表只读,0代表读写 read-only0 #忽略的数据,指不需要同步的数据库 #binlog…...

【C++】入门【五】
本节目标 一、C/C内存分布 二、C语言中动态内存管理方式 三、C中动态内存管理 四、operator new与operator delete函数 五、new和delete的实现原理 六、定位new表达式(placement-new) 七、常见面试题 一、C/C内存分布 一个程序占用的内存主要有以下几部分栈区(stac…...

【React】二、状态变量useState
文章目录 1、React中的事件绑定1.1 基础事件绑定1.2 使用事件对象参数1.3 传递自定义参数1.4 同时传递事件对象和自定义参数 2、React中的组件3、useState 1、React中的事件绑定 1.1 基础事件绑定 语法:on 事件名称 { 事件处理程序 },整体上遵循驼峰…...

SQL Server中的数据处理函数:提升SQL查询能力
文章目录 前言1. 数据类型转换函数CAST()CONVERT()TRY_CAST() 和 TRY_CONVERT() 2. 数学函数ABS()CEILING()FLOOR()ROUND()POWER()SQRT() 3. 日期和时间函数GETDATE()SYSDATETIME()DATEADD()DATEDIFF()YEAR()、MONTH() 和 DAY()FORMAT() 4. 条件处理函数CASEIIF() 总结 前言 在…...

TypeScript 语言学习入门级教程五
在前面的教程中,我们已经逐步深入地学习了 TypeScript 的诸多特性,包括基础语法、类型系统、面向对象编程、装饰器以及一些高级类型等。在本教程中,我们将聚焦于 TypeScript 的模块系统、命名空间与模块的关系、声明文件以及如何在实际项目中…...

上海市计算机学会竞赛平台2022年7月月赛丙组匹配括号(三)
题目描述 如果字符序列仅由 ( 与 ) 构成,则在满足以下条件时,它是匹配的: 空序列是匹配的;如果括号序列 s 是匹配的,那么 (s) 也是匹配的;如果括号序列 s 与 t 是匹配的,那么 st 也是匹配的。…...

108.【C语言】数据结构之二叉树查找值为x的节点
目录 1.题目 代码模板 2.分析 分类讨论各种情况 大概的框架 关键部分(继续递归)的详解 递归调用展开图 3.测试结果 其他写法 4.结论 5.注意事项 不推荐的写法 1.题目 查找值为x的节点并返回节点的地址 代码模板 typedef int BTDataType; typedef struct BinaryT…...

Java学习笔记(10)--面向对象基础
学习资料来自黑马程序员 目录 设计对象并使用 类和对象 定义类 创建类的对象 使用对象 类的几个补充注意事项 设计对象并使用 类和对象 类(设计图):是对象共同特征的描述。 对象:是真实存在的具体东西。 在Java中必须先…...

社群分享在商业引流与职业转型中的作用:开源 AI 智能名片 2+1 链动模式小程序的应用契机
摘要:本文聚焦于社群分享在商业领域的重要性,阐述其作为干货诱饵在引流方面的关键意义。详细探讨了提供有价值干货的多种方式,包括文字分享、问题解答以及直播分享等,并分析了直播分享所需的条件。同时,以自身经历为例…...

nodejs官方文档学习-笔记-1
一、异步工作 process.nextTick(): 回调会在当前操作完成后立即执行,但在事件循环进入下一个阶段之前。它是最先执行的。 Promise.then(): 回调会在 microtask 队列中执行,通常是在当前操作完成后,但在事件循环进入…...

android视频播放器之DKVideoPlayer
一个老牌子的播放器了,项目可能已经有些日子没有维护了。但是使用效果还是不错的。支持多种视频格式,及重力感应、调节亮度等多种效果。想来想去,还是记录下来,我会在文章的最后注明github地址: 首先引入依赖ÿ…...

Linux——基础命令(3)
1.Linux——基础命令(1)-CSDN博客 2.Linux——基础命令(2) 文件内容操作-CSDN博客 一、打包压缩 打包压缩 是日常工作中备份文件的一种方式 在不同操作系统中,常用的打包压缩方式是不同的选项 含义 Windows 常用 rar…...

MySQL备份恢复
华子目录 MySQL日志管理为什么需要日志日志作用日志文件查看方法错误日志通用查询日志慢查询日志示例 撤销日志重做日志二进制日志---重要中继日志 MySQL备份备份类型逻辑备份优缺点备份内容备份工具导入sql文件 MySQL日志管理 为什么需要日志 用于排错用来做数据分析了解程序…...

鲲鹏麒麟安装离线版MySQL5.7
最近有项目需求,需要在鲲鹏ARM服务器上安装数据库MySQL5.7,服务器为鲲鹏920,操作系统Kylin Linux Advanced Server release V10 (Tercel) 安装包 下载地址:https://cloud.189.cn/t/JRVnmeEvMRZ3(访问码:t…...

【不稳定的BUG】__scrt_is_managed_app()中断
【不稳定的BUG】__scrt_is_managed_app函数中断 参考问题详细的情况临时解决方案 参考 发现出现同样问题的文章: 代码运行完所有功能,仍然会中断 问题详细的情况 if (!__scrt_is_managed_app())exit(main_result);这里触发了一个断点很奇怪,这中断就发生了一次,代…...

MyBatis 详解
MyBatis 是一个优秀的 持久层框架,它支持定制化 SQL、存储过程以及高级映射,能够很好地降低 Java 应用程序对数据库操作的复杂性。以下是对 MyBatis 的详细解析: 1. MyBatis 简介 MyBatis 是 Apache 的一款开源框架,其核心特性是…...

Cursor+Devbox AI开发快速入门
1. 前言 今天无意间了解到 Cursor 和 Devbox 两大开发神器,初步尝试以后发现确实能够大幅度提升开发效率,特此想要整理成博客以供大家快速入门. 简单理解 Cursor 就是一款结合AI大模型的代码编辑器,你可以将自己的思路告诉AI,剩下的目录结构的搭建以及项目代码的实现均由AI帮…...

编写按层次顺序(同一层自左至右)遍历二叉树的算法。或:按层次输出二叉树中所有结点;
解:思路:既然要求从上到下,从左到右,则利用队列存放各子树结点的指针是个好办法。 这是一个循环算法,用while语句不断循环,直到队空之后自然退出该函数。 技巧之处:当根结点入队后,会…...

docker 安装mysql8.0.29
docker 安装mysql8.0.29 1、拉取镜像 docker pull mysql:8.0.292、启动容器 docker run -p 3306:3306 --name mysql8.0.29 -e MYSQL_ROOT_PASSWORDroot -d mysql:8.0.29-p 将本地主机的端口映射到docker容器端口(因为本机的3306端口已被其它版本占用,所以使用330…...

vue深入理解输入框字符限制的优化设计
文章目录 深入理解输入框字符限制的优化设计背景与挑战输入框限制的重要性常见需求 多种实现方法解析方法一:基于实时过滤的字符限制方法二:借助正则验证方法三:提交时二次校验 性能优化无障碍设计延伸场景与最佳实践1. 多语言国际化支持2. 动…...

完整指南:在Ubuntu 20.04 ROS 1环境中配置和使用Orbbec SDK
完整指南:在Ubuntu 20.04 ROS 1环境中配置和使用Orbbec SDK 要在Ubuntu 20.04系统中使用ROS 1环境配置和使用Orbbec SDK,可以遵循以下详细且系统化的步骤。这些步骤将引导您从下载必要的工具和SDK到学习如何使用这些资源,确保您能有效地利用…...

【Leetcode Top 100】138. 随机链表的复制
问题背景 给你一个长度为 n n n 的链表,每个节点包含一个额外增加的随机指针 r a n d o m random random,该指针可以指向链表中的任何节点或空节。 构造这个链表的 深拷贝。 深拷贝应该正好由 n n n 个 全新 节点组成,其中每个新节点的值…...