搜索
首页php教程php手册TP 3.2.3 简单解决pgsql无法返回自增主键问题

tp中pgsql向数据库插入数据之后,无法正常返回自增主键,可以考虑使用下面的方法简单处理下
对于pgsql,在使用 add() 方法插入数据之后,返回的结果总是 1,而不是新插入数据的自增 ID。

-----------------------------------------------------------------------------------------------

原因

ThinkPHP 3.2.3 中,所有的数据库都是采用 PDO 方式连接数据库的。PDO 中返回插入数据的自增 ID 的方法是下面的这个方法:string PDO::lastInsertId ([ string $name = NULL ] )参数 name 表示应该返回 ID 的那个序列对象的名称,是可选的。

但是这个函数的具体行为是基于具体的底层驱动实现的。在不同的 PDO 驱动之间,此方法可能不会返回一个有意义或一致的结果,因为底层数据库可能不支持自增字段或序列的概念。

-----------------------------------------------------------------------------------------------

对于 pgsql 来说:PDO_PGSQL() 要求为 name 参数指定序列对象的名称。

而这正是导致问题的所在:
在 ThinkPHP 的 DB 类 Driver.class.php 中,其获取自增 ID 的方式是使用无参数的 lastInsertId() 方法。增加数据后,没有参数时,pgsql 返回的就是 1。

-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------

解决

对于 pgsql,如果要返回正确的自增 ID,必然就是需要在调用 lastInsertId() 方法时添加对应的序列对象的名称(sequence name)。

所以,首先,我们需要在 pgsql 的对应驱动中重写 DB 驱动的`getLastInsID()`方法,给其传入参数:# 位置:ThinkPHP/Library/Think/Db/Driver/Pgsql.class.php<br> /**<br> * 用于获取最后插入的ID<br> * @access public<br> * @return integer<br> */<br> public function getLastInsID($sequenceName) {<br>    return $this->_linkID->lastInsertId($sequenceName);<br> }那么,这个参数应该是什么呢?

一般情况下,pgsql 数据表中设置了自增主键的话,那么自增主键的命名方式为:tableNmae_columnName_seq其中:

* tableName 表示当前表的名称(如果不是 public 命名空间,则需要添加命名空间);
* columnName 表示设置主键的列的名称;
* seq 就是默认设置的,一般不需要修改。

所以,参数不是一个确定的字符串:表名不确定、主键列名不确定:

* 对于表名,我们在用 M() 或者 D() 方法的时候,一般都会传入表名,那么可以考虑在 Model 类中进行拼接参数;
* 对于主键列名,如果做一个约定:数据表中,主键列名均为`id`,那我们就可以绕过去这个问题了。如果不能遵守这个约定,那就只能考虑在 Model 类中增加一个方法来传入对应的参数了。

现在来实现上述的方法,找到并修改 Model 类中的`getLastInsID()`方法:# 位置:ThinkPHP/Library/Think/Model.class.php<br> /**<br> * 返回最后插入的ID<br> * @access public<br> * @return string<br> */<br> public function getLastInsID() {<br>    $col = null;<br>    if (strtolower(C('DB_TYPE')) == 'pgsql')<br>        $col = strtolower($this->trueTableName).'_id_seq';<br> <br>    return $this->db->getLastInsID($col);<br> }这里使用`$this->trueTableName`来获取表名,就可以获取到包含前缀,甚至数据库名的真实表名了,能避免出错。

这样修改之后,基本上就能正常了。但是很快就会发现,有时候还是会出错,提示`relation xx does not exist`。一般这是在访问没有设置主键的表的时候出现的错误。因为使用 pgsql 驱动的`lastInsertId()`方法获取没有主键的表的时候,这个序列对象不存在,于是报错。

知道原因之后,就可以考虑使用`try...catch`语句来重写一下 pgsql 的`lastInsertId()`方法:# 位置:ThinkPHP/Library/Think/Db/Driver/Pgsql.class.php<br> /**<br> * 用于获取最后插入的ID<br> * @access public<br> * @return integer<br> */<br> public function getLastInsID($sequenceName) {<br>    try {<br>        return $this->_linkID->lastInsertId($sequenceName);<br>    } catch (\PDOException $e) {<br>        return $this->lastInsID;<br>    }<br> }MD文档:https://github.com/Lin07ux/notes/blob/master/PHP/ThinkPHP/Thinkphp%20%E8%BF%9E%E6%8E%A5%20pgsql%20%E9%97%AE%E9%A2%98%E5%8F%8A%E8%A7%A3%E5%86%B3.md#add-之后无法返回正确的自增-id

AD:真正免费,域名+虚机+企业邮箱=0元

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。