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. codeforce 139E

    成段更新+离散化才能过,数据好强.. 单点更新挂在了test27,下次做到成段更新再来做! /* 期望=存活概率*点权值/100 ans=sum(期望) 离散化树木权值,数轴统计累加可能倒下的树木概率 ...

  2. 7za的压缩与解压

    2.1 解压缩7z文件 7za x phpMyAdmin-3.3.8.1-all-languages.7z -r -o./ 参数含义: x  代表解压缩文件,并且是按原始目录树解压(还有个参数 e 也 ...

  3. 《Java编程的逻辑》 - 文章列表

    <计算机程序的思维逻辑>系列文章已整理成书<Java编程的逻辑>,由机械工业出版社出版,2018年1月上市,各大网店有售,敬请关注! 京东自营链接:https://item.j ...

  4. hdu 2680 多起点一终点

    注意这是一个有向图! 多起点,一终点 反过来,看成一个起点,多个终点,找最短路 因为是有向图 所以u->v 要也要反过来成为v->u Sample Input5 8 5 //结点数 边数 ...

  5. tomcat常用的配置

    这里我们使用tomcat版本:apache-tomcat-7.0.77-windows-x64.zip 为例:下载链接地址为:https://archive.apache.org/dist/tomca ...

  6. kafka 数据存储结构+原理+基本操作命令

    数据存储结构: Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的.每个topic又可以分成几个不同的partition(每个topic有几个partitio ...

  7. P2152 [SDOI2009]SuperGCD 未完成

    辗转相减求a,b的gcd其实可以优化的: 1.若a为偶数,b为奇数:gcd(a,b)=gcd(a/2,b) 2.若a为奇数,b为偶数:gcd(a,b)=gcd(a,b/2) 3.若a,b都是偶数:gc ...

  8. Python 时间复杂度

    引用自:https://www.cnblogs.com/sch01ar/p/8552295.html

  9. Free DIY Tour HDU1224

    一道很好的dfs加储存路径的题目  :路径保存:每次dfs都存i 当大于max时 将临时数组保存到答案数组 并不是当 当前值大于最大值时更新路径 还要加上一个条件:能回去 #include<bi ...

  10. Linux学习之文件属性chattr权限与sudo权限(十二)

    Linux学习之文件属性chattr权限与sudo权限 文件属性chattr Linux文件的隐藏属性在保护系统文件的安全性上非常重要,是防止误操作的,对root用户也同样有效.chattr命令只能在 ...