PHP中使用PDO进行插入事务处理,lastInsertId 在第二条没有执行正确的情况下会返回上次执行成功的ID
首先我想重现一下这个错误:
测试表单如图,
主表:(先插主表)
附表:(再插附表)
这是我随便建的表,没什么真正的关系,主要是需要先对主表进行数据插入,再主表正确的基础上对附表进行插入。
$db = new DBUtil(); $select = 'select user_id from users where user_email="'.$data['user_email'].'" or user_name="'.$data['user_name'].'"'; $user_id = $db->sqlForArray($select); if($user_id) { echo '用户或者邮箱已经被占用'; } else { //开启事务 $db->db->beginTransaction(); // 插入主表 $db->insertParams( 'insert into users(user_name,user_password,user_email,user_regdate) values(:user_name,:user_password,:user_email,now());', $data ); $last_userid = $db->getLastInsertId; if(!$last_userid) { $db->db->rollBack();exit(); } $db->insertParams('insert into userinfo(user_id,user_qq,user_email,user_weibo,user_description) values('.intval($last_userid).',:user_qq,:user_email,:user_weibo,:user_description);', $meta ); $last_userinfoid = $db->getLastInsertId; var_export($last_userid); var_export($last_userinfoid); if($last_userid && $last_userinfoid) { echo 'commit'; $db->db->commit(); } else { echo '回滚了'; $db->db->rollBack(); } }
上面代码中,insertParams是某类(数据库操作类)sql执行代码,而getLastInsertId是(数据库操作类中返回的最后插入成功的数据id)
如果:
$sth = $this->db->prepare($sql); .... bindParam(...); .... $sth->execute(); return $this->db->lastInsertId();
直接这么写,那么就会出现标题中的错误。这时,使用$this->db->lastInsertId(),第二条没有插入成功,第一条成功了,那么第二条返回的lastInsertId就是第一条的Id
所以处理返回 lastInsertId的代码修改为:
if($sth->execute()) { $this->getLastInsertId = $this->db->lastInsertId(); } else { $this->getLastInsertId = false; }
然后,直接获取db类中的属性getLastInsertId即可。
完!