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 相关文章推荐
phpMyAdmin 安装及问题总结
May 28 PHP
php中获取指定IP的物理地址的代码(正则表达式)
Jun 23 PHP
php页面缓存ob系列函数介绍
Oct 18 PHP
php中生成随机密码的自定义函数代码
Oct 21 PHP
php获取表单中多个同名input元素的值
Mar 20 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十)
Jun 24 PHP
dedecms集成财付通支付接口
Dec 28 PHP
在Linux系统的服务器上隐藏PHP版本号的方法
Jun 06 PHP
Laravel4中的Validator验证扩展用法详解
Jul 26 PHP
Yii 2.0中场景的使用教程
Jun 02 PHP
YII2框架中excel表格导出的方法详解
Jul 21 PHP
Thinkphp极验滑动验证码实现步骤解析
Nov 24 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
PHP中strlen()和mb_strlen()的区别浅析
2014/06/19 PHP
php中namespace use用法实例分析
2016/01/22 PHP
laravel 实现根据字段不同值做不同查询
2019/10/23 PHP
php 多继承的几种常见实现方法示例
2019/11/18 PHP
IE不出现Flash激活框的小发现的js实现方法
2007/09/07 Javascript
javascript 浏览器检测代码精简版
2010/03/04 Javascript
验证javascript中Object和Function的关系的三段简单代码
2010/06/27 Javascript
Javascript Function对象扩展之延时执行函数
2010/07/06 Javascript
模拟jQuery ajax服务器端与客户端通信的代码
2011/03/28 Javascript
js sort 二维数组排序的用法小结
2014/01/24 Javascript
一个JavaScript去除字符串末尾的空白实例代码
2014/09/22 Javascript
js解决select下拉选不中问题
2014/10/14 Javascript
使用变量动态设置js的属性名
2014/10/19 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
JS实现图片剪裁并预览效果
2016/08/12 Javascript
浅谈Nodejs应用主文件index.js
2016/08/28 NodeJs
原生JS实现图片轮播切换效果
2016/12/15 Javascript
webpack里使用jquery.mCustomScrollbar插件的方法
2018/05/30 jQuery
原生JS实现汇率转换功能代码实例
2020/05/13 Javascript
Vue绑定用户接口实现代码示例
2020/11/04 Javascript
python时间整形转标准格式的示例分享
2014/02/14 Python
Python中的一些陷阱与技巧小结
2015/07/10 Python
python实现简单购物商城
2016/05/21 Python
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
Python中的默认参数实例分析
2018/01/29 Python
Python cookbook(数据结构与算法)让字典保持有序的方法
2018/02/18 Python
Python向Excel中插入图片的简单实现方法
2018/04/24 Python
pytorch:torch.mm()和torch.matmul()的使用
2019/12/27 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
CSS3控制HTML元素动画效果
2014/02/08 HTML / CSS
使用HTML5里的classList操作CSS类
2016/06/28 HTML / CSS
注册资产评估专业求职信
2014/07/16 职场文书
2014年作风建设工作总结
2014/10/29 职场文书
生死抉择观后感
2015/06/09 职场文书
公司行政管理制度范本
2015/08/05 职场文书
Redis高并发缓存架构性能优化
2022/05/15 Redis