dsn字符串必须严格符合目标数据库协议规范,错一个字符即报pdo异常;不同数据库的dsn格式、参数名及charset处理方式各不相同,且禁止变量拼接或含空格。

DSN字符串必须按数据库类型严格写,错一个字符就报错
PDO本身不抽象SQL语法,只抽象连接和预处理流程。真正决定能不能连上的,是DSN字符串是否符合目标驱动的协议规范。写错格式不会提示“参数不对”,而是直接抛出 PDOException: could not find driver 或 invalid data source name——这不是配置问题,是PDO根本没认出你想连哪种库。
- MySQL:
mysql:host=localhost;dbname=test;charset=utf8mb4(host和dbname键名不能拼错,charset值要真实支持) - PostgreSQL:
pgsql:host=localhost;dbname=test;user=pguser;password=pgpass(user和password可写在DSN里,也可单独传参) - SQLite:
sqlite:/var/www/db/app.sqlite(必须用绝对路径,sqlite:./data.db这种相对路径在CLI或不同web目录下极易失效) - SQL Server:
sqlsrv:server=localhost;Database=test(Linux需pdo_odbc+FreeTDS,Windows才原生支持sqlsrv)
别用变量拼接DSN,比如 $dsn = "mysql:host={$host};dbname={$db}"; ——看似灵活,但一旦 $host 含特殊字符(如冒号、分号、@),整个DSN就解析失败,且PDO不校验,只静默报错。
PHP8.1里连接多个数据库,得用多个独立PDO实例
一个 PDO 实例只能绑定一个DSN,不能“切换数据库”。想同时操作MySQL和PostgreSQL,就得分别 new 两个对象,各自管理生命周期。这不是设计缺陷,而是PDO有意为之:事务、字符集、连接状态都绑定在实例上,混用会出不可预测行为。
- 不要试图复用同一个
$pdo变量去连不同库,第二次new PDO(...)会覆盖前一个连接,旧连接资源未释放可能泄漏 - 每个实例建议设置独立错误模式:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);,否则默认静默失败,debug时找不到错在哪 - 连接成功后立即测试:
$pdo->query("SELECT 1")->fetchColumn();,比等后续查询报错更早发现问题
DSN里的charset参数在不同数据库中效果不同
charset 不是万能开关。它只对MySQL/PostgreSQL生效,SQLite压根不认这个参数,SQL Server用的是 CharacterSet(且仅部分驱动支持)。PHP8.1默认启用严格模式,如果DSN里写了不支持的键,某些驱动会直接拒绝连接。
- MySQL:
charset=utf8mb4有效,且必须与表实际编码一致,否则中文存成问号 - PostgreSQL:用
options='--client_encoding=UTF8'更可靠,charset参数被忽略 - SQLite:删掉所有
charset=xxx,它只认UTF-8,且不通过DSN设 - 连接后执行
$pdo->exec("SET NAMES utf8mb4")是MySQL兼容写法,但不如DSN里写死来得干净
环境变量注入DSN时,注意URL编码和空格
从 $_ENV 或 getenv() 读取DSN片段(比如密码含 @ 或 ;)时,不编码会破坏DSN结构。例如密码是 pa@ss;word,直接拼进 mysql:host=...;password=pa@ss;word,PDO会把 @ 当作host分隔符,; 当作参数分隔符,结果连到错地址。
- 安全做法:用
urlencode()编码用户名和密码,再拼入DSN(password=' . urlencode($pass) . ') - DSN字符串全程不能含空格,
mysql: host=localhost(中间有空格)会失败,哪怕肉眼看不见 - 推荐用ThinkPHP那种DSN URI格式:
mysql://user:pass@host:3306/dbname?charset=utf8mb4,它内置解析逻辑,比原生DSN容错稍好
最常被忽略的点:SQLite路径权限和PHP进程用户是否可读写;PostgreSQL连接默认走Unix socket而非TCP,host=localhost 可能触发本地认证失败而不是网络连接失败。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











