根据网友的设计进行了部分调整: 用户分为管理员admin表和用户user表

记录操作表数据 增删改: insert/delete/update

<?php
/**
* OperateLog.php
* description
*/ namespace app\service; use think\Db;
use think\Log; /**
* 操作日志
* Class OperateLog
* @package app\service
*/
class OperateLogService
{
// 日志表主键值id
protected $primaryid;
// 操作表的id
protected $tbid;
// 操作表名
protected $tbname;
// 操作表行字段名
protected $keys;
// 操作表行字段值
protected $values;
// 表前缀
protected $prefix;
// 操作用户类型: 1管理员,admin_id | 2用户,user_id
protected $user_type;
protected $user_id = 0;
protected $admin_id = 0;
protected $ip;
const LOGT1 = 'operatelog';
const LOGT2 = 'operatelog_content'; /**
* OperateLog constructor.
* @param int $userType 操作用户类型,1管理员
* @param int $uid 操作用户类型不为1时传入
*/
public function __construct($userType = 1, $uid = 0)
{
if ($userType == 1) {
$this->admin_id = session('admin_id');
} else {
$this->user_id = $uid;
}
$this->user_type = $userType;
$this->ip = ip2long(getIp());
$this->url = request()->url();
$this->prefix = config('database.prefix');
} /**
* 参数说明 插入行为
* int $tbid 查询指定表的id
* string $tbname 数据库表名
*/
public function insert($tbid, $tbname)
{
try {
//查询表注释
$tb = Db::query('show table status where name = "' . $this->prefix . $tbname . '"');
$priIdName = $this->getPrimaryKey($tbname);
$data = [
'type' => 1,
'create_time' => time(),
'tablename' => $tbname,
'tableid' => $tbid,
'tableid_name' => $priIdName,
'admin_id' => $this->admin_id,
'user_id' => $this->user_id,
'user_type' => $this->user_type,
'ip' => $this->ip,
'comment' => $tb['Comment'],
'url' => $this->url,
];
//插入日志主表
$returnid = Db::name(self::LOGT1)->insertGetId($data);
//查询字段注释
$fields = Db::query('show full columns from ' . $this->prefix . $tbname);
foreach ($fields as $v) {
$commentArray[$v['Field']] = $v['Comment'];
}
//查询所有字段信息,插入日志从表
$rs = Db::name($tbname)->where($priIdName, $tbid)->find();
$keys = array_keys($rs);
$values = array_values($rs);
for ($i = 0; $i < count($keys); $i++) {
Db::name(self::LOGT2)->insert([
'operatelog_id' => $returnid,
'tbkey' => $keys[$i],
'tbvalue' => $values[$i],
'comment' => $commentArray[$keys[$i]]
]);
}
} catch (\Exception $e) {
Log::error($e->getMessage());
} } /**
* 更新行为前
* @param $tbid
* @param $tbname
*/
public function updateStart($tbid, $tbname)
{
try {
//查询表注释
$tb = Db::query('show table status where name = "' . $this->prefix . $tbname . '"');
$priIdName = $this->getPrimaryKey($tbname);
$data = [
'type' => 2,
'create_time' => time(),
'tablename' => $tbname,
'tableid' => $tbid,
'tableid_name' => $priIdName,
'admin_id' => $this->admin_id,
'user_id' => $this->user_id,
'user_type' => $this->user_type,
'ip' => $this->ip,
'comment' => $tb['Comment'],
'url' => $this->url,
];
//插入日志主表
$returnid = Db::name(self::LOGT1)->insertGetId($data);
//查询修改前数据信息
$rs = Db::name($tbname)->where($priIdName, $tbid)->find();
$keys = array_keys($rs);
$values = array_values($rs);
$this->primaryid = $returnid;
$this->tbid = $tbid;
$this->tbname = $tbname;
$this->keys = $keys;
$this->values = $values;
} catch (\Exception $e) {
Log::error($e->getMessage());
} } /**
* 更新行为后
*/
public function updateEnd()
{
try {
//查询表注释
$tb = Db::query('show table status where name = "' . $this->prefix . $this->tbname . '"');
$priIdName = $this->getPrimaryKey($this->tbname);
foreach ($tb as $v) {
$commentArray[$v['Field']] = $v['Comment'];
}
//查询修改后数据信息
$rs = Db::name($this->tbname)->where($priIdName, $this->tbid)->find();
$currentvalues = array_values($rs);
//前后信息进行比较
for ($i = 0; $i < count($currentvalues); $i++) {
if ($this->values[$i] !== $currentvalues[$i]) {
Db::name(self::LOGT2)->insert([
'operatelog_id' => $this->primaryid,
'tbkey' => $this->keys[$i],
'tbvalue' => $this->values[$i],
'currenttbvalue' => $currentvalues[$i],
'comment' => $commentArray[$this->keys[$i]]
]);
}
}
} catch (\Exception $e) {
Log::error($e->getMessage());
} } /**
* 删除行为
* @param $tbid
* @param $tbname
*/
public function delete($tbid, $tbname)
{
try {
//查询表注释
$tb = Db::query('show table status where name = "' . $this->prefix . $this->tbname . '"');
$priIdName = $this->getPrimaryKey($this->tbname);
$data = [
'type' => 3,
'create_time' => time(),
'tablename' => $tbname,
'tableid' => $tbid,
'tableid_name' => $priIdName,
'admin_id' => $this->admin_id,
'user_id' => $this->user_id,
'user_type' => $this->user_type,
'ip' => $this->ip,
'comment' => $tb['Comment'],
'url' => $this->url,
];
//插入日志主表
$returnid = Db::name(self::LOGT1)->insertGetId($data);
//查询字段注释
$fields = Db::query('show full columns from ' . $this->prefix . $tbname);
foreach ($fields as $v) {
$commentArray[$v['Field']] = $v['Comment'];
}
//查询修改前数据信息
$rs = Db::name($tbname)->where($priIdName, $tbid)->find();
$keys = array_keys($rs);
$values = array_values($rs);
for ($i = 0; $i < count($keys); $i++) {
Db::name(self::LOGT2)->insert([
'operatelog_id' => $returnid,
'tbkey' => $keys[$i],
'tbvalue' => $values[$i],
'comment' => $commentArray[$keys[$i]]
]);
}
} catch (\Exception $e) {
Log::error($e->getMessage());
} } /**
* 查询表主键id名
* @param $tbname
* @return mixed
*/
protected function getPrimaryKey($tbname)
{
$priIdTb = Db::query("SELECT column_name FROM INFORMATION_SCHEMA.`KEY_COLUMN_USAGE` WHERE table_name='" . $this->prefix . $tbname . "' AND constraint_name='PRIMARY'");
return $priIdTb[0]['column_name'];
}
}

数据表设计:

CREATE TABLE `yed_operatelog` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned DEFAULT '0' COMMENT 'user表用户id',
`admin_id` int(11) unsigned DEFAULT '0' COMMENT 'admin表主键:管理员id',
`user_type` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '操作用户类型:1管理员,admin_id | 2用户,user_id',
`type` tinyint(1) NOT NULL DEFAULT '1' COMMENT '操作类型:1新增2修改3删除',
`tableid` int(11) unsigned NOT NULL,
`tablename` varchar(255) NOT NULL COMMENT '表名',
`comment` varchar(255) DEFAULT NULL COMMENT '表的comment属性',
`create_time` int(11) unsigned NOT NULL COMMENT '创建时间',
`tableid_name` varchar(50) NOT NULL DEFAULT '' COMMENT '主键id名',
`ip` int(11) DEFAULT NULL COMMENT '操作ip',
`url` varchar(800) DEFAULT NULL COMMENT '操作url',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COMMENT='操作日志表'; CREATE TABLE `yed_operatelog_content` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`operatelog_id` int(11) NOT NULL COMMENT 'operatelog表id',
`tbkey` longtext NOT NULL COMMENT '字段名',
`tbvalue` longtext COMMENT '改之前值',
`currenttbvalue` longtext COMMENT '改之后值',
`comment` varchar(255) DEFAULT NULL COMMENT '字段注释',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='操作日志从表';

TP5数据库数据变动日志记录设计的更多相关文章

  1. C#日志记录设计与实现(BenXHLog)

    C#日志记录设计与实现 日志记录: 日志记录在程序设计开发过程中,是非常重要的,可以供调试和记录数据,虽然说有开源的强大日志管理系统,比如apache的Log4Net,功能可谓强悍,但是有时候,不需要 ...

  2. mysql数据库安全性配置——日志记录

    一:开启数据库日志记录 (1)在查看数据库是否开启日志记录,默认是OFF,即关闭状态.(可在数据库中执行该查询语句,也可在服务器端执行) show variables like 'log_bin'; ...

  3. shell脚本之分析oracle数据库数据泵日志中表的大小

    1.分析日志格式如下 . . imported "xxx_330508"."xxx_T_DATA" 46.17 MB 268 rows . . imported ...

  4. (转)解释一下SQLSERVER事务日志记录

    本文转载自桦仔的博客http://www.cnblogs.com/lyhabc/archive/2013/07/16/3194220.html 解释一下SQLSERVER事务日志记录 大家知道在完整恢 ...

  5. 解释一下SQLSERVER事务日志记录

    解释一下SQLSERVER事务日志记录 大家知道在完整恢复模式下,SQLSERVER会记录每个事务所做的操作,这些记录会存储在事务日志里,有些软件会利用事务日志来读取 操作记录恢复数据,例如:log ...

  6. wcf利用IDispatchMessageInspector实现接口监控日志记录和并发限流

    一般对于提供出来的接口,虽然知道在哪些业务场景下才会被调用,但是不知道什么时候被调用.调用的频率.接口性能,当出现问题的时候也不容易重现请求:为了追踪这些内容就需要把每次接口的调用信息给完整的记录下来 ...

  7. 扔掉log4j、log4j2,自己动手实现一个多功能日志记录框架,包含文件,数据库日志写入,实测5W+/秒日志文件写入,2W+/秒数据库日志写入,虽然它现在还没有logback那么强大

    讲到log4j,现在国外基本是没有开发者用这个框架了,原因大致有几点,1.功能太少:2.效率低下:3.线程锁bug等等等各种莫名其妙的bug一直都没解决. 其实最重要的是log4j的作者自己也放弃了l ...

  8. tp5下通过composer实现日志记录功能

    tp5实现日志记录 1.安装 psr/log composer require psr/log 它的作用就是提供一套接口,实现正常的日志功能! 我们可以来细细的分析一下,LoggerInterface ...

  9. 也用 Log4Net 之将日志记录到数据库的后台实现 (二)

    也用 Log4Net 之将日志记录到数据库的后台实现 (二)  大家下午好,昨天讲了配置,今天我们讲讲后台实现,在完成了后台实现后,我们才能真正意义上的解决把自定义属性字段值录入到数据库中. 在开写之 ...

随机推荐

  1. Git-04-本地仓库撤销修改

    编辑修改了文件,但是还没有git add之前 直接用 git checkout -- filename 这个命令就可以了 已经 git add 了,但是没有 git commit 之前 1 模拟git ...

  2. mysqldump备份恢复数据

    //导出数据(多个表以空格间隔)mysqldump -h 127.0.0.1 -uroot -p123456 --default-character-set=utf8 pandora report & ...

  3. Block循环引用详解

    前言 在项目中经常用到block,使用不当就很容易因为循环引用而造成内存泄漏.本文分析了block循环引用形成原因以及处理办法,如果有什么不对或者疑问请留言. 什么情况下block会造成循环引用 bl ...

  4. 【LeetCode】88. 合并两个有序数组

    88. 合并两个有序数组 知识点:数组:排序:双指针: 题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 ...

  5. Python 读写文件的正确方式

    当你用 Python 写程序时,不论是简单的脚本,还是复杂的大型项目,其中最常见的操作就是读写文件.不管是简单的文本文件.繁杂的日志文件,还是分析图片等媒体文件中的字节数据,都需要用到 Python ...

  6. @Profile-根据不同环境注入bean

    介绍 @Profile元注解是在不同的生产环境中,@Bean创建的SpringBean根据spring.profiles.active指定的环境不同创建不同环境的bean对象 一.@Profile元注 ...

  7. chcon命令详解

    导读 chcon命令是修改对象(文件)的安全上下文,比如:用户.角色.类型.安全级别.也就是将每个文件的安全环境变更至指定环境.使用--reference选项时,把指定文件的安全环境设置为与参考文件相 ...

  8. mysql基础操作(三):数据约束

    首先创建一个数据库 create database homework default character set utf8; use homework; 1.1 默认值约束(default) -- 数 ...

  9. Docker安装MySQL集群【读写分离】

    Centos7系统Docker安装 目录 Centos7系统Docker安装 目录 Centos7系统Docker安装 1.下载mysql镜像 2.创建Master实例并启动 参数说明 3.创建Sla ...

  10. 使用Visual Studio分析dump

    最近系统是不是CPU会飙升的百分之九十多甚至百分百,在本地又很难复现问题,无法定位问题出现在哪. 可以用转储文件来保存现场,然后通过分析dump文件可以大概分析出问题的所在 生成转存文件 在CPU飙升 ...