mysqli_connect()默认只触发Warning不抛异常,需显式检查返回值或调用mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT)启用异常模式。

mysqli_connect() 报 Warning 而不是 Exception 怎么办
PHP8.1 默认把 MySQL 连接失败转为 Warning,而不是抛出异常——这意味着错误不会中断执行,但会直接输出到页面或日志,影响调试和用户体验。根本原因在于 mysqli_connect() 是“静默失败型”函数,它只返回 false,不自动触发异常。
- 不要用
@mysqli_connect(...)简单压制警告:这会掩盖真实问题,且 PHP8.1 中部分警告(如 SSL 配置失败)仍可能穿透 @ 屏蔽 - 正确做法是显式检查返回值,并手动触发
throw new RuntimeException(...)或trigger_error(..., E_USER_ERROR) - 示例:
$conn = mysqli_connect($host, $user, $pass, $db, $port, $socket); if (!$conn) { throw new RuntimeException('MySQL connect failed: ' . mysqli_connect_error() . ' (' . mysqli_connect_errno() . ')'); }
MySQL 5.7 socket 路径不一致导致连接警告
常见现象是 mysqli_connect(): (HY000/2002): No such file or directory,本质是 PHP 找不到 MySQL 的 Unix socket 文件。PHP 和 MySQL 各自配置了不同路径,比如 MySQL 实际用 /var/lib/mysql/mysql.sock,而 PHP 读取的是 mysqli.default_socket = /tmp/mysql.sock(默认值)。
- 查 MySQL 实际 socket:登录 MySQL 执行
STATUS,看 “UNIX socket” 行 - 查 PHP 当前配置:运行
php -i | grep mysqli.default_socket或在phpinfo()页面搜mysqli.default_socket - 统一路径:修改
php.ini中的mysqli.default_socket值为 MySQL 实际 socket 路径,然后重启 PHP 进程(如 php-fpm 或 Apache) - 临时绕过:连接时显式传 socket 参数,
mysqli_connect($host, $user, $pass, $db, $port, '/var/lib/mysql/mysql.sock')
用户权限或认证插件引发的 Access denied Warning
MySQL 5.7 默认用 mysql_native_password 插件,但若管理员手动改过用户认证方式(比如误设为 caching_sha2_password),PHP8.1 的 mysqli 仍能连,但会在日志里报 Access denied for user 类警告,实际连接却成功——这是因认证协商阶段失败但回退机制生效了。
- 确认用户插件:执行
SELECT host, user, plugin FROM mysql.user WHERE user = 'your_user'; - 强制还原插件:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_pass'; FLUSH PRIVILEGES; - 避免 root 直连:开发环境别用 root 用户,新建专用账号并限定 host(如
'app'@'127.0.0.1'),再授最小必要权限 - 注意密码为空时:MySQL 5.7 对空密码校验更严,
''和NULL行为不同,建议显式设为''而非省略
SQL mode 严格导致的零日期警告干扰连接
MySQL 5.7 开启了 NO_ZERO_DATE 和 NO_ZERO_IN_DATE 后,某些旧业务代码插入 '0000-00-00' 会触发警告;这些警告虽不阻断连接,但会混在连接日志里,让人误以为是连接问题。
立即学习“PHP免费学习笔记(深入)”;
- 这不是连接层问题,但常被误判:检查警告内容是否含
Incorrect date value或Invalid default value - 临时关闭(仅开发环境):
SET sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';(去掉 ZERO 相关项) - 长期方案:在应用层过滤零日期,或建表时用
DATE NULL DEFAULT NULL替代NOT NULL DEFAULT '0000-00-00' - 注意:PHP 本身不控制 SQL mode,它完全由 MySQL 服务端决定,PHP 只负责传递和接收警告



















