thinkphp3.2.3(5以下)的addAll返回值问题

背景(欲快速解决问题,直接看最后一部分即可)

我们都知道mysql支持一次插入多条数据,如下:
以用户表user为例,表结构自增主键id、账号username、密码password。

insert into user(username,password) values ('fpf','123456'),('pig','258310');

TP借助PDO连接mysql,完成上述操作。

除了增删改查,PDO还有一些函数,如lastInsertId(返回最后插入行的ID)、PDOStatement::rowCount(返回上一个由对应的 PDOStatement 对象执行DELETE、 INSERT、或 UPDATE 语句受影响的行数)等。参考1参考2

问题

对于tp3.2.3的addAll方法,发现其返回值与官方文档说的返回最后一个id不一样,而是返回第一个id。比如用addAll方法向user表中一次插入1、2、3共三条数据,它返回的是第1条数据的id,而非官方定义的第3条数据的id。

$m=M('User');
$data=[['username'=>'fpf','password'=>'123456'],['username'=>'pig','password'=>'258310']];
$pk=$m->addAll($data);
dump($pk);

运行该带码,dump的数据是5,而在数据库中
id=5对应数据[‘username’=>‘fpf’,‘password’=>‘123456’];
id=6对应数据[‘username’=>‘pig’,‘password’=>‘258310’]。
显然tp官方文档定义相悖。

原因

追查TP3.2.3的ORM实现机制发现,其addAll方法的返回值直接用pdo的lastInsertId方法获得,在tp目录ThinkPHP\Library\Think\Db下的Driver.class.php文件的execute方法中,具体实现方法如下:

在这里插入图片描述问题就在pdo的lastInsertId方法上,它是调用mysql api中的mysql_insert_id函数返回的值。
mysql_insert_id函数和SELECT LAST_INSERT_ID()作用类似,但又有一些区别,在下面代码情景中作用相同,具体不同看官方文档,直接在数据库管理工具(如navicat)上执行下面mysql脚本就会发现问题。

insert into user(username,password) values ('fpf','123456'),('pig','258310');
SELECT LAST_INSERT_ID()

在这里插入图片描述实际结果:
在这里插入图片描述
从两个图片结果可以看到,一次插入两条,通过SELECT LAST_INSERT_ID()查到的id=24,而实际最后一个id=25,这是什么原因呢?具体原因可以看看这篇官方对该语句的解释,这是mysql的一个处理策略,主要是因为可以轻松地实现其他服务器复制相同的INSERT语句。当然,在一次插入一条时,这个现象时不存在的,那么mysql_insert_id返回的结果也就正确了。
在这里插入图片描述

mysql官方文档介绍mysql_insert_id函数解释如下:详细参考官方文档

官方文档主要说了mysql_insert_id函数返回的是储存在有AUTO_INCREMENT约束的字段的值,如果表中的字段不使用AUTO_INCREMENT约束或者使用自己生成的唯一值插入,那么该函数不会返回你所存储的值,而是返回NULL或0。因此,在没有使用AUTO_INCREMENT约束的表中,或者ID是自己生成的唯一ID,lastInsertId函数返回的都是0。

也可以参考这两篇文章,有实际例子说明,更好,重点看看第一篇。文章1文章2

解决方案

利用pdo的rowCount方法,具体代码如下:
原理:lastID=firstID+rowCount-1;
在这里插入图片描述具这样修改TP3.2.3的addAll方法就可以正常放回最后一行的id了。
样另外TP5及以上一次插入多条的方法是insertAll,它返回的是添加成功的条数,当然,这些方法的前提都是插入执行成功。将tp3.2.3目录ThinkPHP\Library\Think\Db下的Driver.class.php文件的execute方法改成下图即可:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值