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动态图像的创建
Oct 09 PHP
Email+URL的判断和自动转换函数
Oct 09 PHP
php debug 安装技巧
Apr 30 PHP
php中使用explode查找某个字符是否存在的方法
Jul 12 PHP
PHP遍历XML文档所有节点的方法
Mar 12 PHP
Nginx下配置codeigniter框架方法
Apr 07 PHP
ThinkPHP连接Oracle数据库
Apr 22 PHP
PHP文件操作详解
Dec 30 PHP
php生成0~1随机小数的方法(必看)
Apr 05 PHP
ThinkPHP实现静态缓存和动态缓存示例代码
May 02 PHP
PHP的静态方法与普通方法用法实例分析
Sep 26 PHP
在laravel5.2中实现点击用户头像更改头像的方法
Oct 14 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时间戳与日期之间转换的实例介绍
2013/04/19 PHP
深入php self与$this的详解
2013/06/08 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
PHP实现的简单缓存类
2015/07/29 PHP
PHP实现随机生成水印图片功能
2017/03/22 PHP
javascript编程起步(第四课)
2007/02/27 Javascript
js hover 定时器(实例代码)
2013/11/12 Javascript
js实现省市联动效果的简单实例
2014/02/10 Javascript
js实现文本框中输入文字页面中div层同步获取文本框内容的方法
2015/03/03 Javascript
JQuery控制radio选中和不选中方法总结
2015/04/15 Javascript
JQuery节点元素属性操作方法
2015/06/11 Javascript
javascript模拟C#格式化字符串
2015/08/26 Javascript
JavaScript原生对象常用方法总结(推荐)
2016/05/13 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
微信小程序链接传参并跳转新页面
2016/11/29 Javascript
node koa2实现上传图片并且同步上传到七牛云存储
2017/07/31 Javascript
jquery将信息遍历到界面上实例代码
2020/01/21 jQuery
解决vue请求接口第一次成功,第二次失败问题
2020/09/08 Javascript
openlayers实现地图弹窗
2020/09/25 Javascript
[02:21]DOTA2英雄基础教程 蝙蝠骑士
2013/12/16 DOTA
使用python调用浏览器并打开一个网址的例子
2014/06/05 Python
浅谈python中列表、字符串、字典的常用操作
2017/09/19 Python
python爬虫简单的添加代理进行访问的实现代码
2019/04/04 Python
OpenCV图像颜色反转算法详解
2019/05/13 Python
Python应用领域和就业形势分析总结
2019/05/14 Python
12个不为大家熟知的HTML5设计小技巧
2016/06/02 HTML / CSS
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
四川internet信息高速公路(C#)笔试题
2012/02/29 面试题
村委会贫困证明
2014/01/14 职场文书
婚纱摄影师求职信
2014/03/07 职场文书
幼儿园大班毕业教师寄语
2014/04/03 职场文书
巾帼文明岗申报材料
2014/05/01 职场文书
国贸专业求职信
2014/06/28 职场文书
向国旗敬礼活动总结范文2014
2014/09/27 职场文书
2015年设计师个人工作总结
2015/04/25 职场文书
2016年父亲节寄语
2015/12/04 职场文书