浅谈管理系统操作日志设计(附操作日志类)
管理系统的操作日志如何做成通用的模块一直是个让我头疼的问题,不过看了博客园里的某篇文章后,现在基本解决了。
相关文章链接:《系统操作日志设计》
在开始做之前,必须把两个日志分清楚,那就是普通操作日志和业务操作日志,这两者有何区别?
在我理解,普通操作日志就是单表的操作记录,而业务操作日志则就是一系列的普通操作日志的集合。
打个比方,用户需要购买一样宝贝,已经到了下单那步,下单就是个业务,这个业务背后就是一系列的业务,如:
生成订单 → 生成商品快照 → 发送一条站内信 → 删除购物车里对应宝贝
这样一个下单操作就包含了4部分,可以把这4部分看成是4张表,分别对这4张表进行对应的操作,就实现了业务。
但今天我要讲的不是业务操作日志,因为不同项目的业务不尽相同,所以它无法做成通用模块,而我要讲的,就是普通操作日志。
上面解释了一大段,下面干货就要亮相了,先洗把脸清醒下。
……
首先,哪些地方需要记录操作日志?执行insert、update、delete这3个操作的时候,就需要进行日志,而日志执行的先后顺序如下
insert | 在insert后执行 |
update | 在update前后都要执行,操作前获取操作前数据,操作后获取操作后数据 |
delete | 在delete前执行 |
顺序清楚后,就来看下我写的一份日志操作类吧,第一版随便写写的,重复代码有点多,还未来得及优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | class LOG{ protected $primaryid ; protected $tbid ; protected $tbname ; protected $keys ; protected $values ; /** * 参数说明 * int $tbid 查询指定表的id * string $tbname 数据库表名 */ public function insert( $tbid , $tbname ){ global $db ; //查询表注释 $db ->query( 'show table status where name = "' . $tbname . '"' ); $tb = $db ->fetch(); //插入日志主表 $returnid = $db ->insert(0, 2, 'tb_log' , array ( 'adminid = ' . $_SESSION [ 'admin' ][ 'id' ], 'type = 1' , 'tableid = ' . $tbid , 'tablename = "' . $tbname . '"' , 'comment = "' . $tb [ 'Comment' ]. '"' , 'dt = now()' )); //查询字段注释 $db ->query( 'show full columns from ' . $tbname ); $tb = $db ->fetchAll(); foreach ( $tb as $v ){ $commentArray [ $v [ 'Field' ]] = $v [ 'Comment' ]; } //查询所有字段信息,插入日志从表 $rs = $db ->select(0, 1, $tbname , '*' , 'and tbid = ' . $tbid ); $keys = array_keys ( $rs ); $values = array_values ( $rs ); for ( $i = 0; $i < count ( $keys ); $i ++){ $db ->insert(0, 0, 'tb_log_content' , array ( 'logid = ' . $returnid , 'tbkey = "' . $keys [ $i ]. '"' , 'tbvalue = "' . $values [ $i ]. '"' , 'comment = "' . $commentArray [ $keys [ $i ]]. '"' )); } } public function updateStart( $tbid , $tbname ){ global $db ; //查询表注释 $db ->query( 'show table status where name = "' . $tbname . '"' ); $tb = $db ->fetch(); //插入日志主表 $returnid = $db ->insert(0, 2, 'tb_log' , array ( 'adminid = ' . $_SESSION [ 'admin' ][ 'id' ], 'type = 2' , 'tableid = ' . $tbid , 'tablename = "' . $tbname . '"' , 'comment = "' . $tb [ 'Comment' ]. '"' , 'dt = now()' )); //查询修改前数据信息 $rs = $db ->select(0, 1, $tbname , '*' , 'and tbid = ' . $tbid ); $keys = array_keys ( $rs ); $values = array_values ( $rs ); $this ->primaryid = $returnid ; $this ->tbid = $tbid ; $this ->tbname = $tbname ; $this ->keys = $keys ; $this ->values = $values ; } public function updateEnd(){ global $db ; //查询字段注释 $db ->query( 'show full columns from ' . $this ->tbname); $tb = $db ->fetchAll(); foreach ( $tb as $v ){ $commentArray [ $v [ 'Field' ]] = $v [ 'Comment' ]; } //查询修改后数据信息 $rs = $db ->select(0, 1, $this ->tbname, '*' , 'and tbid = ' . $this ->tbid); $currentvalues = array_values ( $rs ); //前后信息进行比较 for ( $i = 0; $i < count ( $currentvalues ); $i ++){ if ( $this ->values[ $i ] !== $currentvalues [ $i ]){ $db ->insert(0, 0, 'tb_log_content' , array ( 'logid = ' . $this ->primaryid, 'tbkey = "' . $this ->keys[ $i ]. '"' , 'tbvalue = "' . $this ->values[ $i ]. '"' , 'currenttbvalue = "' . $currentvalues [ $i ]. '"' , 'comment = "' . $commentArray [ $this ->keys[ $i ]]. '"' )); } } } public function delete ( $tbid , $tbname ){ global $db ; //查询表注释 $db ->query( 'show table status where name = "' . $tbname . '"' ); $tb = $db ->fetch(); //插入日志主表 $returnid = $db ->insert(0, 2, 'tb_log' , array ( 'adminid = ' . $_SESSION [ 'admin' ][ 'id' ], 'type = 3' , 'tableid = ' . $tbid , 'tablename = "' . $tbname . '"' , 'comment = "' . $tb [ 'Comment' ]. '"' , 'dt = now()' )); //查询字段注释 $db ->query( 'show full columns from ' . $tbname ); $tb = $db ->fetchAll(); foreach ( $tb as $v ){ $commentArray [ $v [ 'Field' ]] = $v [ 'Comment' ]; } //查询所有字段信息,插入日志从表 $rs = $db ->select(0, 1, $tbname , '*' , 'and tbid = ' . $tbid ); $keys = array_keys ( $rs ); $values = array_values ( $rs ); for ( $i = 0; $i < count ( $keys ); $i ++){ $db ->insert(0, 0, 'tb_log_content' , array ( 'logid = ' . $returnid , 'tbkey = "' . $keys [ $i ]. '"' , 'tbvalue = "' . $values [ $i ]. '"' , 'comment = "' . $commentArray [ $keys [ $i ]]. '"' )); } } } |
使用前,需要引入数据库操作类,这是我之前写的一份,可参考《全新的PDO数据库操作类(仅适用Mysql)》。
引入之后,就可以开始使用了。
select
1 | $log ->insert(82, 'tb_member' ); |
update
1 2 3 | $log ->updateStart(82, 'tb_member' ); //中间放更新操作代码 $log ->updateEnd(); |
delete
1 | $log -> delete (82, 'tb_member' ); |
可以看到,一共只需要两个参数即可,分别是表ID(主键)和表名称。
另外需要强调一点,表注释和字段注释一定要完整,因为记录的信息包含注释,目的就是为了查阅的时候能清楚哪个字段是干什么用的。
下面就看下成品吧
最后把表结构分享下,一共2张表,一张主表一张从表,主表记录操作表及操作人等信息,从表记录操作的表字段信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | -- ---------------------------- -- Table structure for `tb_log` -- ---------------------------- CREATE TABLE `tb_log` ( `tbid` bigint (20) NOT NULL AUTO_INCREMENT, `adminid` bigint (20) DEFAULT NULL COMMENT '管理员id' , `type` tinyint(4) DEFAULT '1' COMMENT '操作类型:1新增2修改3删除' , `tableid` bigint (20) DEFAULT NULL , `tablename` varchar (255) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '表名' , `comment` varchar (255) COLLATE utf8_unicode_ci DEFAULT NULL , `dt` datetime DEFAULT NULL , PRIMARY KEY (`tbid`) ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 COLLATE =utf8_unicode_ci; -- ---------------------------- -- Table structure for `tb_log_content` -- ---------------------------- CREATE TABLE `tb_log_content` ( `tbid` bigint (20) NOT NULL AUTO_INCREMENT, `logid` bigint (20) DEFAULT NULL , `tbkey` longtext COLLATE utf8_unicode_ci, `tbvalue` longtext COLLATE utf8_unicode_ci, `currenttbvalue` longtext COLLATE utf8_unicode_ci, `comment` varchar (255) COLLATE utf8_unicode_ci DEFAULT NULL , PRIMARY KEY (`tbid`) ) ENGINE=InnoDB AUTO_INCREMENT=109 DEFAULT CHARSET=utf8 COLLATE =utf8_unicode_ci; |
hooray.github.io
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2011-09-05 EonerCMS——做一个仿桌面系统的CMS(二)