新项目优先用 pdo,老项目维护或简单脚本用 mysqli_connect() 更轻量;pdo 支持多数据库、需设异常模式,mysqli 仅限 mysql、错误需手动检查,且 localhost 与 127.0.0.1 连接机制不同。

PHP 连接 MySQL 用 mysqli_connect() 还是 new PDO()
直接说结论:新项目优先用 PDO,老项目维护或简单脚本用 mysqli_connect() 更轻量。两者都能连,但底层行为、错误处理和预处理支持差异明显。
常见错误现象:mysqli_connect(): (HY000/1045): Access denied for user... 或 Call to undefined function mysqli_connect()(没开扩展)。
-
PDO支持多种数据库(MySQL、PostgreSQL、SQLite),换库时改 DSN 即可,mysqli只认 MySQL -
PDO默认不抛异常,得手动设PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,否则错也静默 -
mysqli_connect()返回资源或false,必须用mysqli_connect_error()拿错误信息,容易漏判 - PHP 8.1+ 已废弃
mysql_*函数,别碰mysql_connect()—— 它早没了
连接字符串里 localhost 和 127.0.0.1 居然不一样
不是笔误,是真实坑点:用 localhost 会走 Unix socket(Linux/macOS),用 127.0.0.1 才走 TCP。某些环境(比如 Docker 容器间通信、SELinux 严格模式)下,localhost 直接连不上。
典型表现:mysqli_connect(): (HY000/2002): No such file or directory(socket 文件路径不对)或超时。
立即学习“PHP免费学习笔记(深入)”;
一个功能强大的B2B与B2C的购物平台,除了原本OSC功能外,增加更新的功能: 一、 取消了register_globals必须开启的限制 二、 將HTML程式碼与PHP程式碼完全分离,採用了smarty 樣板引擎 三、 每支档案includes所需函数与资料库连结,使的网页显示速度明显提升 四、 检视、购买商品群组权限设定 五、 十八岁以下禁购机制 六、 折价券购物抵扣机制 七、 礼券购物机制
- 本地开发调试,优先写
127.0.0.1,排除 socket 路径干扰 - 生产环境若明确走 socket(性能略好),查 MySQL 配置:
mysql -e "SHOW VARIABLES LIKE 'socket';",然后在 PHP 里补全路径:mysqli_connect('localhost:/var/run/mysqld/mysqld.sock', ...) - Docker Compose 场景下,数据库服务名(如
db)才是正确 host,localhost指容器自己,不是宿主机或另一容器
密码含特殊字符(如 @、/、:)导致连接失败
URL 形式 DSN(比如 PDO 的 mysql:host=localhost;dbname=test)里,密码若含 @、/、:、?,会被解析器截断或误判。这不是 PHP Bug,是 URL 解析规则。
错误示例:$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'p@ss/w0rd'); —— 实际连的密码只剩 p。
- 用
urlencode()包一层密码:urlencode('p@ss/w0rd')→p%40ss%2Fw0rd - mysqli 不走 URL 解析,所以
mysqli_connect($host, $user, $pass)没这问题,但要注意传参顺序别错 - 更稳妥做法:把敏感配置放环境变量或配置文件,避免硬编码;用
getenv('DB_PASS')+urldecode()统一处理
连接后立刻执行查询却报 Commands out of sync
这是 mysqli 特有错误,意思是上一个查询的结果集没取完(比如没调 mysqli_fetch_all() 或循环读完),就又发了新查询。PDO 默认不会这样,但 mysqli 很容易踩。
典型场景:函数里执行 SELECT 后没清空结果,返回前又调了一次 mysqli_query()。
- 每次
mysqli_query()后,确保用mysqli_free_result()或读完所有行 - 批量操作慎用
mysqli_multi_query(),它更容易触发这个错,普通场景用单条query()更稳 - 开启持久连接(
mysqli_pconnect())时更危险——连接复用,残留结果集会跨请求传染
复杂点在于:这个错不总在出问题那行报,可能延迟到下个查询才爆,排查时容易定位错位置。连完先做个小 SELECT 1 测试,比等业务逻辑崩了再 debug 快得多。










