根据网友的设计进行了部分调整: 用户分为管理员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. 数据结构与算法-排序(七)希尔排序(Shell Sort)

    摘要 看希尔排序需要先想象出一个二维的矩阵,在这个矩阵中,有多少列数据全看步长(一定的规则得到).处理完之后,就再接着用另一个步长组成矩阵处理.直到步长全部使用完. 这里的巧妙之处就是没有把序列先处理 ...

  2. Git(6)-- 记录每次更新到仓库(git clone、status、add、diff、commit、rm、mv命令详解)

    @ 目录 1.克隆现有仓库:git clone 2.检查当前文件状态 :git status 3.跟踪新文件:git add 4.暂存已修改的文件:git add 5.状态简览: git status ...

  3. 【笔记】主成分分析法PCA的原理及计算

    主成分分析法PCA的原理及计算 主成分分析法 主成分分析法(Principal Component Analysis),简称PCA,其是一种统计方法,是数据降维,简化数据集的一种常用的方法 它本身是一 ...

  4. HTML5内嵌文本编辑器

    1.这个编辑器用的是KindEditor 先看下效果: 2.准备: a):从官网下载KindEditor--->http://kindeditor.net/down.php b):解压到桌面测试 ...

  5. NOIP 模拟 $28\; \rm 遗忘之祭仪$

    题解 \(by\;zj\varphi\) 直接贪心模拟即可,对于每个点,如果它未被覆盖,直接在这覆盖一次. 每个黑点只会被扫一次,所以总复杂度为 \(\mathcal O\rm (nm)\) Code ...

  6. Java社区——个人项目开发笔记(一)

    1.maven安装与测试 安装过程略,常用的maven命令行工具: mvn --version 查看maven版本 mvn compile 编译maven工程 mvn clean 删除编译文件 mvn ...

  7. C#实现http协议GET、POST请求

    using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Ne ...

  8. Spring详解(四)------注解配置DI

    第一步:在 applicationContext.xml 中引入命名空间 这里我们简单讲解一下这里引入的命名空间,简单来说就是用来约束xml文件格式的.第一个 xmlns:context ,这表示标签 ...

  9. Struts2之OGNL与ValueStack

    时间:2017-1-12 12:02 --OGNL1.OGNL表达式是什么    OGNL的全称是Object-Graph Navigation Language的缩写,中文名是对象图导航语言,它是一 ...

  10. 工具库用久了,你还会原生操作 Cookie 吗?

    用得好了,工具库和框架确实是一大助力,但就怕我们会因此习惯了走捷径,而忘了自己的根本依靠是什么. 前言 前端技术的飞速发展,给从业人员不可避免地带来了"疲劳"感,我们常常会感叹学不 ...