php 8.2 连接 postgresql 15 必须启用 pdo_pgsql 和 pgsql 扩展,dsn 需显式指定 port、user、password,且必须使用 prepare() + execute() 预处理防止注入;游标慎用,推荐 limit/offset 或游标分页。

PHP 8.2 连接 PostgreSQL 15 必须启用 pdo_pgsql 和 pgsql
PHP 8.2 默认不加载 PostgreSQL 扩展,哪怕你装了 PostgreSQL 15,new PDO("pgsql:...") 仍会报 Driver not found。必须手动启用两个扩展:pdo_pgsql(PDO 驱动)和 pgsql(原生函数支持,部分工具链依赖它)。CentOS/RHEL 上用 yum install php-pgsql 即可同时安装二者;Debian/Ubuntu 则需 apt install php-pgsql。装完后运行 php -m | grep pgsql,输出两行(pdo_pgsql 和 pgsql)才算完整。
pgsql:host= DSN 中的 port 和 user/password 不是可选的
PostgreSQL 15 默认监听 5432,但若改过端口、或用 Docker 启动(如 -p 5433:5432),DSN 里必须显式写 port=5433,否则连接超时。另外,PostgreSQL 15 强制要求认证方式(如 scram-sha-256),如果 DSN 没带 user 和 password,即使数据库允许 trust 本地登录,PDO 也会因凭证缺失直接抛 PDOException。正确写法是:
$dsn = "pgsql:host=localhost;port=5432;dbname=myapp;user=appuser;password=secret123";
硬编码密码仅用于测试;生产环境务必从 $_ENV 或配置文件读取。
prepare() + execute() 是唯一安全的查询方式
PostgreSQL 15 对 SQL 注入更敏感,尤其涉及 JSONB 字段或动态表名时。pg_query() 或字符串拼接 "SELECT * FROM $table WHERE id = $id" 在 PHP 8.2 下可能通过语法检查,但实际执行会被 scram-sha-256 认证拦截,或触发 ERROR: invalid input syntax for type jsonb 等隐式错误。PDO 的预处理能将参数与 SQL 语义分离:
-
prepare()把 SQL 发给 PostgreSQL 编译成执行计划,不带参数 -
execute()只传参数值,服务端按类型强校验(比如:status绑定整数,不会被当字符串解析) - 即使用户输入
1 OR 1=1,绑定后也只当字面量1处理
示例:
$stmt = $pdo->prepare("SELECT * FROM orders WHERE status = :status AND created_at >= :since");
$stmt->execute(['status' => 2, 'since' => '2024-01-01']);
游标(CURSOR_SCROLL)在 PostgreSQL 15 + PHP 8.2 中可用但慎用
PostgreSQL 15 原生支持可滚动游标,PDO 的 PDO::CURSOR_SCROLL 能生效(不同于 MySQL 的静默降级)。但要注意两点:
- 必须在
prepare()时传[PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL],仅setAttribute()无效 - 每次
fetch()都触发一次网络往返,大数据集下比fetchAll()慢 3–5 倍;仅适合分页深度跳转(如“跳到第 1000 页”)
多数 Web 场景用 LIMIT/OFFSET 或游标分页(WHERE id > ? LIMIT 20)更稳。
PostgreSQL 15 的认证机制和类型系统比旧版更严格,PHP 8.2 的 PDO 扩展恰好提供了匹配的参数绑定与错误反馈能力;跳过 DSN 细节、绕过预处理,容易在上线后遇到认证失败或数据类型转换异常,这类问题往往不报错,只返回空结果。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











