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、要求开发者建表时要按照规范,写字段注释

优化

针对于每次验证都需要查询表结构,建议上缓存,查询后把表结构放在缓存里,当表结构发生变化时需要及时更新缓存,如果有更好的想法欢迎交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/62952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

限定符使用

正则表达式的元字符一次一般只能匹配一个位置或一个字符,如果想要匹配零个、一个或多个字符时,则需要使用限定符。限定符用于指定允许特定字符或字符集自身重复出现的次数。常用限定符如下: <asp:TextBox [^>]> 正则表达式字符类[^>]匹配除过“>”之外的任何字…

vue3+vite 批量引入组件动态使用

import { ref, reactive, toRaw, markRaw, defineAsyncComponent, onMounted } from vue import type { Component } from vue// vue3vite 批量引入组件动态使用 const modules import.meta.glob<Component>(./details/*.vue) // 明确指定导入的模块类型为Component con…

电脑关机的趣味小游戏——system函数、strcmp函数、goto语句的使用

文章目录 前言一. system函数1.1 system函数清理屏幕1.2 system函数暂停运行1.3 system函数电脑关机、重启 二、strcmp函数三、goto语句四、电脑关机小游戏4.1. 程序要求4.2. 游戏代码 总结 前言 今天我们写一点稍微有趣的代码&#xff0c;比如写一个小程序使电脑关机&#xf…

VScode离线下载扩展安装

在使用VScode下在扩展插件时&#xff0c;返现VScode搜索不到插件&#xff0c;网上搜了好多方法&#xff0c;都不是常规操作&#xff0c;解决起来十分麻烦&#xff0c;可以利用离线下载安装的方式安装插件&#xff01;亲测有效&#xff01;&#xff01;&#xff01; 1.找到VScod…

数据结构基础之《(10)—快速排序》

一、快速排序基础 1、Partition过程 给定一个数组arr&#xff0c;和一个整数num。请把小于等于num的数放在数组的左边&#xff0c;大于num的数放在数组的右边。 要求额外空间复杂度O(1)&#xff0c;时间复杂度O(N) 2、例子 区分小于等于num的数 (<区) [5 3 7 2 3 4 1] num…

2023年第十四届蓝桥杯Scratch国赛真题—推箱子

推箱子 程序演示及其源码解析&#xff0c;可前往&#xff1a; https://www.hixinao.com/scratch/creation/show-188.html 若需在线编程&#xff0c;在线测评模考&#xff0c;助力赛事可自行前往题库中心&#xff0c;按需查找&#xff1a; https://www.hixinao.com/ 题库涵盖…

学习threejs,使用VideoTexture实现视频Video更新纹理

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️VideoTexture 视频纹理 二、…

Xilinx PCIe高速接口入门实战(一)

引言&#xff1a;本文对Xilinx 7 Series Intergrated Block for PCI Express PCIe硬核IP进行简要介绍&#xff0c;主要包括7系列FPGA PCIe硬核资源支持、三IP硬核差异、PCIe硬核资源利用等相关内容。 1. 概述 1.1 7系列FPGA PCIe硬件资源支持 7系列FPGA对PCIe接口最大支持如…

浪潮X86服务器NF5280、8480、5468、5270使用inter VROC Raid key给NVME磁盘做阵列

Inter VROC技术简介 Intel Virtual RAID on CPU (Intel VROC) 简单来说就是用CPU的PCIE通道给NVME硬盘做Raid 更多信息可以访问官方支持页面 Raid Key 授权&#xff0c;即VROC SKU 授权主要有用的有2个标准和高级&#xff0c;仅Raid1的授权我暂时没见过。 标准 VROCSTANMOD …

Google Cloud 混合云部署连接方式最佳实践案例讲解

混合云部署连接方式 GCP 的混合云部署连接方式提供了多种选择&#xff0c;企业可以根据自身需求选择合适的解决方案。实施最佳实践&#xff0c;将有助于提高混合云架构的性能、安全性和可用性。通过合理的规划和管理&#xff0c;企业可以充分利用混合云的优势&#xff0c;实现…

计算机网络之应用层协议HTTP

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 应用层协议HTTP 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. HTTP …

PyTorch 2.5.1: Bugs修复版发布

一&#xff0c;前言 在深度学习框架的不断迭代中&#xff0c;PyTorch 社区始终致力于提供更稳定、更高效的工具。最近&#xff0c;PyTorch 2.5.1 版本正式发布&#xff0c;这个版本主要针对 2.5.0 中发现的问题进行了修复&#xff0c;以提升用户体验。 二&#xff0c;PyTorch 2…

集合的相关性质与定义

集合 集合 集合描述了一组对象的集合&#xff0c;而映射描述了集合之间的对应关系。 集合 集合是由一组无序的&#xff0c;互不相同的对象组成的整体&#xff0c;集合中的对象称为元素或成员。集合可以用大括号{}表示,元素之间用逗号进行分隔。 定义&#xff1a; 集合 A …

【Golang】Golang基础语法(二):内建变量类型

内建变量类型 Go 的内建变量类型: bool, string(u)int, int8, int16, int32, int64, uintptr(指针, go的指针比C的指针方便很多)byte(8位), rune(32位)(Go的字符类型, 相当于Go的char类型)float32, float64, complex64, complex128 强制类型转换 Golang 当中的类型转换只能…

文件管理:文件描述符fd

1.前置预备 文件 内容 属性访问文件之前&#xff0c;都必须先打开他 #include<stdio.h> int main() { FILE* fpfopen("log.txt","w"); if(fpNULL) { perror("fopen"); return 1; } fclose(fp); return 0…

电脑显示没信号显示屏不亮怎么办?电脑没信号解决方法

电脑没信号显示屏不亮这种故障的原因可能有多种&#xff0c;例如显示器的供电、连接、设置等问题&#xff0c;或者电脑的显卡、内存、硬盘、主板等硬件问题。所以我们想要解决这个问题&#xff0c;也是需要多方面排除找到具体原因然后进行修复。下面将为大家介绍一些常见的电脑…

WPF从本地文件加载界面

在前面的文章中&#xff0c;我介绍过一种报告模板的实现思路。就是用的XAML本地加载。 WPF使用XAML实现报表的一种思路&#xff08;支持外部加载&#xff09; - zhaotianff - 博客园 在另外一篇文章中&#xff0c;介绍了XAML是如何被转换成对象的。 WPF中的XAML是如何转换成对…

Microi吾码产品深度测评:轻量级企业管理应用的全方位剖析

开源低代码平台-Microi吾码-平台简介 技术框架&#xff1a;.NET8 Redis MySql/SqlServer/Oracle Vue2/3 Element-UI/Element-Plus 平台始于2014年&#xff08;基于Avalon.js&#xff09;&#xff0c;2018年使用Vue重构&#xff0c;于2024年10月29日开源 Vue3试用地址&am…

ArrayList如何深究?最简单的数组~

目录 数组 Array 为什么数组索引从0开始呢&#xff1f;为什么不从1开始&#xff1f; ArrayList 成员变量 构造方法 添加和扩容 ArrayList底层的实现原理是什么&#xff1f; 数组和List转换 ArrayList 和 LinkedList区别 底层数据结构 操作数据效率 内存占用 线程安…

C++ 分治

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 1.分治法 2.二分搜索 函数传参——数组 3.棋盘覆盖 4.合并排序 5.快速排序 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.分治法 基…