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. hdu1540

    怎么会T啊 /* 三种操作:D x:第x个位置1 Q x:查询第x位置所在的0连续块 R :将上次D的位置置0 */ #include<iostream> #include<algo ...

  2. python接口自动化测试二十六:使用pymysql模块链接数据库

     #!/usr/bin/env python# -*- coding: utf-8 -*-# @Time    : 2018/5/28 18:51# @Author  : StalloneYang#  ...

  3. eclipse中Ruby环境搭建

    用Eclipse学习Watir.Eclipse支持Ruby的插件:RDT(Ruby Development Tools),下载下来试用了一下,感觉还是不错的.第一步:获取RDT,通过以下链接可以获得R ...

  4. Hibernate之关联关系映射(一对一主键映射和一对一外键映射)

    1:Hibernate的关联关系映射的一对一外键映射: 1.1:第一首先引包,省略 1.2:第二创建实体类: 这里使用用户信息和身份证信息的关系,用户的主键编号既可以做身份证信息的主键又可以做身份证信 ...

  5. Hibernate的四种查询方式(主键查询,HQL查询,Criteria查询,本地sql查询)和修改和添加

    Hibernate的添加,修改,查询(三种查询方式)的方法: 案例演示: 1:第一步,导包,老生常谈了都是,省略: 2:第二步,创建数据库和数据表,表结构如下所示: 3:第三步创建实体类User.ja ...

  6. S2750&S5700&S6700 V200R003(C00&C02&C10) MIB参考

    https://support.huawei.com/enterprise/docinforeader.action?contentId=DOC1000027337&idPath=791971 ...

  7. Zookeeper笔记(二)Paxos算法与Zookeeper的工作原理

    Zookeeper 分布式服务框架是 Apache Hadoop 的一个子项目, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务.状态同步服务.集群管理.分布式应用配置项的管 ...

  8. (APIO2014)序列分割

    题解: 我也不知道为啥上午上课讲了我昨天看的3题 这题关键在于发现操作顺序无关的 可以发现最终答案是任意两段乘积的和 那这个东西显然是可以dp的 然后可以斜率优化一波 nklongn 另外上课讲的是当 ...

  9. python函数式编程——偏函数

    当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单. import functools def te ...

  10. IE浏览器url中带中文报错的问题;以及各种兼容以及浏览器问题总结

    1.解决IE浏览器url带中文报错 /* encodeURI()解决IE浏览器请求url中带中文报错的问题 */ URL = encodeURI("<%=basePath%>ve ...