Thinkphp中的模型可以对数据库字段进行验证规则的设置和设置一些字段的默认值(比如字段为当前时间)以及在操作数据时的的一些回调方法等
 
基本上每一个模型都需要设置一些验证规则和字段默认值的设置,而大部分都存在着重复的工作
 
特别是像需要将数据库操作记录到日志系统的,这就导致我们需要在每个模型中反复处理
 
针对此问题我定义一个父类模型,所以模型都继承自此类即可解决以上两个问题
 
父类就完成了以下两件工作:
 
  1. 记录增、删、改等操作到日志系统
  2. 定义一些大部分数据库都需要验证的规则(子类可覆盖或自定义)或者需要自动生成的字段(如每个数据库都有一个记录当前时间的字段create_time)
 
<?php
/* *
* 公共模型
*/
namespace Common\Model;
use Think\Model;
class CommonModel extends Model {
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 12:22:19
* @Description: 验证字段,子类可以覆盖或移出
*/
protected $_validate = array(
array('code','require','{%ERROR_NOT_PAST}'),//必须
array('name','require','{%ERROR_NOT_PAST}'),//必须
);
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 12:08:38
* @Description: 所有继承的子类字段create_time自动生成当前时间
*/
protected $_auto = array (
array ('create_time', 'mGetDate', 1, 'callback' ), // 增加的时候调用回调函数
);
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 15:52:40
* @Description: 返回该类的自动验证信息,用于在子类中合并该验证信息(不能在子类中定义此$_validate属性否则会被覆盖,如果不需要在子类中合并则可以可忽略此方法)
*/
protected function get_validate()
{
return $this->_validate;
}
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 12:06:03
* @Description: 获取当前时间
*/
protected function mGetDate() {
return date ( 'Y-m-d H:i:s' );
} /**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 10:50:20
* @Description: 更新成功后的回调方法
*/
protected function _after_update($data,$options) {
//区分会员登录和更改操作
if( $options['model']=="Users"
&& $data['last_login_ip']
&& $data['last_login_time']
&& count($data)==3
)
{
$this->after_write("login",$data,$options);
}
else{
$this->after_write("update",$data,$options);
}
}
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 10:50:27
* @Description: 插入成功后的回调方法
*/
protected function _after_insert($data,$options) {
$this->after_write("insert",$data,$options);
} /**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 11:56:12
* @Description: 删除成功后的回调方法
*/
protected function _after_delete($data,$options) {
$this->after_write("delete",$data,$options);
}
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 11:03:18
* @Description: 更新或插入成功后和删除前写入系统日志
*/
function after_write($type,$data,$options)
{
$db_name = C('DB_PREFIX')."system_log"; //日志表
//如果是系统日志表则不处理,防止循环调用此方法
if(!$this->_is_array($data) || !$this->_is_array($options) || strcasecmp($options['table'],$db_name)==0) return ;
$model = M("SystemLog"); //日志表
$new_value = json_encode($data); // 去除前缀的表名
$_data['log_table'] = str_replace(C('DB_PREFIX'), "",$options['table']);
//更改时如果原数据未更改则不进行记录,防止重复记录
if("update" === $type){
//表主健
$_data['t_id'] = $data['id']; // 主健名称不是id
// 获取主健对应的数据
if($_data['id']){
$tablename = $options['table'];
$_data['t_id'] = $data[M($tablename)->getPk()];
}
// 如果最后一条的值没有更改则不记录
if($model->where($_data)->order("id desc")->getField("new_value")===$new_value) return;
}
$_data['log_type'] = $type;
$_data['new_value'] = $new_value;
$_data['log_user'] = $_SESSION['ADMIN_ID'];
$_data['create_time'] = date('Y-m-d H:i:s');
$_data['ip_address'] = get_client_ip(0,true);
$_data['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
try {
$model->add($_data);
} catch (Exception $e) {
\Think\Log::write('写入系统日志时发生错误,错误信息:'.$e->getMessage(),'WARN');
}
}
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 11:04:40
* @Description: 是否是数组
*/
function _is_array($array)
{
return ($array && is_array($array) && count($array)>0);
}
}

  

 
 
定义一个数据库模型并继承自CommonModel即可
 
<?php

 /**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 12:03:57
* @Description: 基础价格Model
*/
namespace Common\Model;
use Common\Model\CommonModel;
class PriceModel extends CommonModel
{
/**
* @Author: HTL
* @Email: Huangyuan413026@163.com
* @DateTime: 2016-04-08 15:01:46
* @Description: 自动验证,合并父类验证规则
*/
function _initialize() { //自定义验证规则
$_val = array(
array('cost','/^[-0-9]{1,}$/','{%ERROR_ONLY_INTEGER}'),
array('price','/^[-0-9]{1,}$/','{%ERROR_ONLY_INTEGER}'),
); //合并父类的规则
//验证父类code、name字段
//当前模型的create_time字段自动填充
$this->_validate = array_merge (parent::get_validate(),$_val); // 移出父类的Code唯一性验证
//foreach ($this->_validate as $key => $value) {
// if($value[0]=='code' && $value[4]=='unique'){
// unset($this->_validate[$key]);
// }
//} //覆盖父类验证规则
$this->_validate = $_val;
}
}

  

 
数据库结构
CREATE TABLE `tp_system_log` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`log_type` VARCHAR(50) NOT NULL COMMENT '操作类别',
`log_table` VARCHAR(100) NOT NULL COMMENT '操作的表',
`log_user` VARCHAR(100) NOT NULL COMMENT '操作的用户',
`t_id` VARCHAR(50) NOT NULL COMMENT '操作的表的主健ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作的时间',
`new_value` TEXT NOT NULL COMMENT '操作后的新值',
`ip_address` VARCHAR(20) NOT NULL COMMENT 'Ip地址',
`user_agent` VARCHAR(500) NULL DEFAULT NULL COMMENT 'User-Agent:',
PRIMARY KEY (`id`),
INDEX `id` (`id`)
)

  

 
参考:

TP3.1开发手册 模型扩展

ThinikPhp 将数据库模型的增、删、改操作写入日志的更多相关文章

  1. C# ADO.NET (sql语句连接方式)(增,删,改)

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  2. 好用的SQL TVP~~独家赠送[增-删-改-查]的例子

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化.  本系列主要是针对T-SQL的总结. [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础] ...

  3. iOS sqlite3 的基本使用(增 删 改 查)

    iOS sqlite3 的基本使用(增 删 改 查) 这篇博客不会讲述太多sql语言,目的重在实现sqlite3的一些基本操作. 例:增 删 改 查 如果想了解更多的sql语言可以利用强大的互联网. ...

  4. ADO.NET 增 删 改 查

    ADO.NET:(数据访问技术)就是将C#和MSSQL连接起来的一个纽带 可以通过ADO.NET将内存中的临时数据写入到数据库中 也可以将数据库中的数据提取到内存中供程序调用 ADO.NET所有数据访 ...

  5. MVC EF 增 删 改 查

    using System;using System.Collections.Generic;using System.Linq;using System.Web;//using System.Data ...

  6. 第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据

    第18课-数据库开发及ado.net 连接数据库.增.删.改向表中插入数据并且返回自动编号.SQLDataReade读取数据 ADO.NET 为什么要学习? 我们要搭建一个平台(Web/Winform ...

  7. django ajax增 删 改 查

    具于django ajax实现增 删 改 查功能 代码示例: 代码: urls.py from django.conf.urls import url from django.contrib impo ...

  8. StringBuilder修改字符串内容,增,删,改,插

    package seday01;/** * 字符串不变对象特性只针对字符串重用,并没有考虑修改操作的性能.因此String不适合频繁修改内容. * 若有频繁修改操作,使用StringBuilder来完 ...

  9. iOS FMDB的使用(增,删,改,查,sqlite存取图片)

    iOS FMDB的使用(增,删,改,查,sqlite存取图片) 在上一篇博客我对sqlite的基本使用进行了详细介绍... 但是在实际开发中原生使用的频率是很少的... 这篇博客我将会较全面的介绍FM ...

随机推荐

  1. 2017-2018-2 20155225《网络对抗技术》实验九 Web安全基础

    2017-2018-2 20155225<网络对抗技术>实验九 Web安全基础 WebGoat 1.String SQL Injection 题目是想办法得到数据库所有人的信用卡号,用Sm ...

  2. 《剑指offer》-青蛙跳台阶II

    一只青蛙一次可以跳上1级台阶,也可以跳上2级--它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 其实题目很水...就是一个等比数列通项公式嘛 f(0)=1 f(1)=1 f(n)=f( ...

  3. struts2的文件上传和文件下载

    实现使用Struts2文件上传和文件下载: 注意点: (1)对应表单的file1和私有成员变量的名称必须一致 <input type="file" name="fi ...

  4. SpringBoot前端给后端传list

    前端JS "]; var params = { taskList: taskList }; $.ajax({ type: "PUT", dataType: "j ...

  5. P1562 还是N皇后

    P1562 还是N皇后原来,就会位运算搞八皇后,当复习一下.可行的位置是1,其他是0比如11011到下一行的时候,对应的左斜线和右斜线要移一位 #include<iostream> #in ...

  6. Mongodb - 切片搭建

    0.概述 mongodb分片搭建,版本号4.0.2,以下除了创建opt文件夹以外,所有操作均在mongodb用户下面执行 准备三台机器:192.168.56.81192.168.56.82192.16 ...

  7. 启动oracle command

    @echo off net start OracleXETNSListener >nul net start OracleServiceXE >nul

  8. Cocos2d-X开发教程-捕鱼达人 Cocos2-x development tutorial - fishing talent

    Cocos2d-X开发教程-捕鱼达人 Cocos2-x development tutorial - fishing talent 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱 ...

  9. prufer序列计数的一些结论

    \(prufer\)序列和完全图的生成树一一对应(考虑构造) 完全图的生成树个数为\(n^{n - 2}\) 满足第\(i\)个点的度数为\(d_i\)的生成树为\(\frac{n!}{\prod ( ...

  10. 10.30 正睿停课训练 Day12

    目录 2018.10.30 正睿停课训练 Day12 A 强军战歌(DP 树状数组 容斥) B 当那一天来临(思路) C 假如战争今天爆发(贪心) 考试代码 B C 2018.10.30 正睿停课训练 ...