pdo扩展未启用导致class 'pdo' not found,需安装php-pgsql包或配置php.ini启用pdo_pgsql;dsn格式须严格,host不可省略,port须为整数,特殊字符密码需url编码。

pdo_pgsql 扩展没启用,new PDO() 直接报错 Class 'PDO' not found
PHP 8.5 默认不启用 pdo_pgsql,哪怕系统装了 PostgreSQL 客户端库也没用。错误不是连不上数据库,而是压根找不到驱动。
- 先确认扩展是否加载:
php -m | grep pdo_pgsql,没输出就得手动开 - Linux(apt):装
php-pgsql包,不是postgresql-client - macOS(Homebrew):确保
php@8.5是通过--with-pgsql编译的,或重装时加该选项 - Windows:检查
php.ini里有没有这行:extension=pdo_pgsql(注意不是pgsql单独扩展) - 重启 PHP-FPM 或 Apache,CLI 和 Web 环境的
php.ini可能不同,别只改了一个
DSN 字符串写错,PDO::__construct() 报 SQLSTATE[08006] [7] could not connect to server
PostgreSQL 的 DSN 格式比 MySQL 更严格,少一个参数、多一个空格、端口写成字符串都会失败。
- 标准格式是:
pgsql:host=localhost;port=5432;dbname=testdb;user=pguser;password=pgpass -
host不能省——即使本地连接也得显式写host=127.0.0.1或host=localhost;用host=/var/run/postgresql表示 Unix socket 路径 -
port必须是整数,写成port="5432"(带引号)会静默失效,回退到默认 5432,但若服务实际在 5433 就连不上 - 密码含特殊字符(如
@、/、:)必须 URL 编码,例如password=a%40b%2Fc - 测试连通性别只靠 PHP:先用
psql -h localhost -p 5432 -U pguser testdb手动验证
连接后查不出数据,PDOStatement::fetch() 返回 false 或空数组
不是连接问题,是事务隔离或权限导致的“看不见”。PostgreSQL 默认开启事务,且 pguser 可能没被授 SELECT 权限。
- 确认表存在且大小写匹配:
SELECT * FROM "MyTable"(双引号表示大小写敏感),而SELECT * FROM mytable会被转成小写 - 检查用户权限:
SELECT has_table_privilege('pguser', 'testtable', 'SELECT'); - 如果用
PDO::ATTR_EMULATE_PREPARES => false(推荐),某些复杂查询(如含 CTE 的)可能触发服务器端预编译限制,临时关掉试试 - 字段名含大写字母时,
fetch(PDO::FETCH_ASSOC)返回的键名是小写的,除非建表时用双引号定义列名
PHP 8.5 的 PDO::ATTR_ERRMODE 默认值变了,错误不抛异常
PHP 8.5 中 PDO::ATTR_ERRMODE 默认仍是 PDO::ERRMODE_SILENT,但很多人误以为它自动变成 EXCEPTION,结果 query() 失败也不报错,只返回 false。
立即学习“PHP免费学习笔记(深入)”;
- 显式设置:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - 别在
new PDO()第四个参数里传,那个参数只接受驱动选项(如PDO::PGSQL_ATTR_DISABLE_PREPARES) - 连接失败时,
PDOException的getMessage()通常包含真实错误(如role "pguser" does not exist),比静默失败好排错得多 - 注意:开启异常后,所有 PDO 操作都需
try/catch,否则脚本直接终止
事情说清了就结束。最常卡住的其实是 DSN 里的 host 和扩展是否真正加载——其他都是次要的。











