thinkphp3.2.0 setInc方法 源码全面解析


Posted in PHP onJanuary 29, 2018

我们先来看一下setInc的官方示例:

thinkphp3.2.0 setInc方法 源码全面解析

需要一个字段和一个自增的值(默认为1)

我们通过下面这个例子来一步步分析他的底层是怎么实现的:

<?php
namespace Home\Controller;
use Think\Controller;

class TestController extends Controller {
  public function test() {
    $tb_test = M('test');
    $tb_test->where(['id'=>1])->setInc('test_number',2); //每次添加2
    dump($tb_test->getLastSql());
    //string(67) "UPDATE `tb_test` SET `test_number`=test_number+2 WHERE ( `id` = 1 )"
  }
}

第一步肯定是要找到setInc方法的源码:

这里我用到了phpstrom全局搜索的方法,找到了setInc是在proj\ThinkPHP\Library\Think\Model.class.php下

/**
   * 字段值增长
   * @access public
   * @param string $field 字段名
   * @param integer $step 增长值
   * @return boolean
   */
  public function setInc($field,$step=1) {
    return $this->setField($field,array('exp',$field.'+'.$step));
  }

可以看到这里用到了setField这个方法,然后用exp自定义表达式设置 $field = $field + $step 到这里,我们稍微了解了一点原理。

可是问题又来了setField又是怎么实现的呢?在同个文件下,找到setField方法:

/**
   * 设置记录的某个字段值
   * 支持使用数据库字段和方法
   * @access public
   * @param string|array $field 字段名
   * @param string $value 字段值
   * @return boolean
   */
  public function setField($field,$value='') {
    if(is_array($field)) {
      $data      =  $field;
    }else{
      $data[$field]  =  $value;
    }
    return $this->save($data);
  }

这里我们看到了常用到的save方法,这里的 $data[$field] = $value; 其实就是 $data['test_number'] = array("exp","test_number+2")

接着来看最常用的save方法:

/**
   * 保存数据
   * @access public
   * @param mixed $data 数据
   * @param array $options 表达式
   * @return boolean
   */
  public function save($data='',$options=array()) {
    if(empty($data)) {
      // 没有传递数据,获取当前数据对象的值
      if(!empty($this->data)) {
        $data      =  $this->data;
        // 重置数据
        $this->data   =  array();
      }else{
        $this->error  =  L('_DATA_TYPE_INVALID_');
        return false;
      }
    }
    // 数据处理
    $data    =  $this->_facade($data);
    // 分析表达式
    $options  =  $this->_parseOptions($options);
    $pk     =  $this->getPk();
    if(!isset($options['where']) ) {
      // 如果存在主键数据 则自动作为更新条件
      if(isset($data[$pk])) {
        $where[$pk]     =  $data[$pk];
        $options['where']  =  $where;
        unset($data[$pk]);
      }else{
        // 如果没有任何更新条件则不执行
        $this->error    =  L('_OPERATION_WRONG_');
        return false;
      }
    }
    if(is_array($options['where']) && isset($options['where'][$pk])){
      $pkValue  =  $options['where'][$pk];
    }    
    if(false === $this->_before_update($data,$options)) {
      return false;
    }    
    $result   =  $this->db->update($data,$options);
    if(false !== $result) {
      if(isset($pkValue)) $data[$pk]  = $pkValue;
      $this->_after_update($data,$options);
    }
    return $result;
  }

最主要是的$options = $this->_parseOptions($options);和$result = $this->db->update($data,$options); 前者把参数转换成用于拼接sql的字符串数组,后者调用了proj\tptest\ThinkPHP\Library\Think\Db.class.php下的update方法:

/**
   * 更新记录
   * @access public
   * @param mixed $data 数据
   * @param array $options 表达式
   * @return false | integer
   */
  public function update($data,$options) {
    $this->model =  $options['model'];
    $sql  = 'UPDATE '
      .$this->parseTable($options['table'])
      .$this->parseSet($data)
      .$this->parseWhere(!empty($options['where'])?$options['where']:'')
      .$this->parseOrder(!empty($options['order'])?$options['order']:'')
      .$this->parseLimit(!empty($options['limit'])?$options['limit']:'')
      .$this->parseLock(isset($options['lock'])?$options['lock']:false)
      .$this->parseComment(!empty($options['comment'])?$options['comment']:'');
    return $this->execute($sql,$this->parseBind(!empty($options['bind'])?$options['bind']:array()));
  }

最后其实就是用到了proj\ThinkPHP\Library\Think\Db\Driver\Mysql.class.php这个驱动类的execute方法。

/**
   * 执行语句
   * @access public
   * @param string $str sql指令
   * @return integer|false
   */
  public function execute($str) {
    $this->initConnect(true);
    if ( !$this->_linkID ) return false;
    $this->queryStr = $str;
    //释放前次的查询结果
    if ( $this->queryID ) {  $this->free();  }
    N('db_write',1);
    // 记录开始执行时间
    G('queryStartTime');
    $result =  mysql_query($str, $this->_linkID) ;
    $this->debug();
    if ( false === $result) {
      $this->error();
      return false;
    } else {
      $this->numRows = mysql_affected_rows($this->_linkID);
      $this->lastInsID = mysql_insert_id($this->_linkID);
      return $this->numRows;
    }
  }

最后用最底层的mysql_query执行SQL语句。

到此为止,setInc的源码已经大致过了一遍了。想必大家对setInc如何执行也更了解了一点。

以上这篇thinkphp3.2.0 setInc方法 源码全面解析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用PHP动态生成虚拟现实VRML网页
Oct 09 PHP
一个PHP模板,主要想体现一下思路
Dec 25 PHP
PHP实现域名whois查询的代码(数据源万网、新网)
Feb 22 PHP
discuz程序的PHP加密函数原理分析
Aug 05 PHP
SESSION信息保存在哪个文件目录下以及能够用来保存什么类型的数据
Jun 17 PHP
php判断字符串在另一个字符串位置的方法
Feb 27 PHP
PHP中单引号与双引号的区别分析
Aug 19 PHP
PHP获取Exif缩略图的方法
Jul 13 PHP
php获取本机真实IP地址实例代码
Mar 31 PHP
thinkphp,onethink和thinkox中验证码不显示的解决方法分析
Jun 06 PHP
php接口技术实例详解
Dec 07 PHP
PHP实现APP微信支付的实例讲解
Feb 10 PHP
Ubuntu上安装yaf扩展的方法
Jan 29 #PHP
PHP实现的防止跨站和xss攻击代码【来自阿里云】
Jan 29 #PHP
php实现的AES加密类定义与用法示例
Jan 29 #PHP
php 判断IP为有效IP地址的方法
Jan 28 #PHP
Laravel中unique和exists验证规则的优化详解
Jan 28 #PHP
win10 apache配置虚拟主机后localhost无法使用的解决方法
Jan 27 #PHP
PHP设计模式之注册树模式分析
Jan 26 #PHP
You might like
xajax写的留言本
2006/11/25 PHP
CI框架中libraries,helpers,hooks文件夹详细说明
2014/06/10 PHP
PHP7.0安装笔记整理
2015/08/28 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
PHP的PDO预处理语句与存储过程
2019/01/27 PHP
使用新的消息弹出框blackbirdjs
2008/10/16 Javascript
js猜数字小游戏的简单实现代码
2013/07/02 Javascript
JQUERY dialog的用法详细解析
2013/12/19 Javascript
5种处理js跨域问题方法汇总
2014/12/04 Javascript
jQuery实现图片局部放大镜效果
2016/03/17 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
2016/05/19 Javascript
jquery插件锦集【推荐】
2016/12/16 Javascript
用jQuery旋转插件jqueryrotate制作转盘抽奖
2017/02/10 Javascript
vue 使用Jade模板写html,stylus写css的方法
2018/02/23 Javascript
详解如何在微信小程序中愉快地使用sass
2018/07/30 Javascript
基于vue通用表单解决方案的思考与分析
2019/03/16 Javascript
基于vue手写tree插件的那点事儿
2019/08/20 Javascript
vue 解决遍历对象显示的顺序不对问题
2019/11/07 Javascript
js实现打字小游戏
2019/12/17 Javascript
使用django-suit为django 1.7 admin后台添加模板
2014/11/18 Python
Python实现求两个csv文件交集的方法
2017/09/06 Python
对web.py设置favicon.ico的方法详解
2018/12/04 Python
Python阶乘求和的代码详解
2020/02/14 Python
Selenium向iframe富文本框输入内容过程图解
2020/04/10 Python
土耳其国际性时尚购物网站:Modanisa
2018/01/19 全球购物
教师岗位职责
2013/11/17 职场文书
安全技术说明书
2014/05/09 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
巴西世界杯32强口号
2014/06/05 职场文书
毕业设计指导教师评语
2014/12/30 职场文书
教师党员承诺书2015
2015/01/21 职场文书
幼儿园教师求职信
2015/03/20 职场文书
房地产项目合作意向书
2015/05/08 职场文书
谢师宴家长答谢词
2015/09/30 职场文书
用Python远程登陆服务器的步骤
2021/04/16 Python
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
2021/06/05 Python