1045错误本质是PHP与MySQL凭据不匹配:需验证.env是否生效(APP_DEBUG=true、位置正确、键名全大写)、确认DB_HOST与mysql.user中user@host精确一致(localhost≠127.0.0.1)、检查认证插件是否兼容(MySQL 8.0+推荐改用mysql_native_password),并用命令行直连绕过框架验证底层连接。

PHP8连接MySQL时提示1045错误,说明数据库凭据不匹配,不是代码写错了,而是PHP实际传给MySQL的账号密码与服务端存储的用户信息对不上——必须逐层验证凭证是否真正加载、是否被正确解析、是否在MySQL中存在对应权限记录。
确认PDO异常里的真实线索
打开runtime/log/下最新那条带PDOException的完整日志,重点看message字段末尾括号内容:【(using password: YES)】表示PHP传了密码但MySQL拒绝了,大概率是密码错或用户不存在;【(using password: NO)】表示PHP根本没传密码,DB_PASSWORD为空、null或被trim成空字符串。
如果日志里只显示“数据库连接失败”,说明APP_DEBUG=false,ThinkPHP8跳过了.env加载逻辑,直接放弃读取配置。
验证.env是否真的生效
方法一:检查APP_DEBUG是否为true。APP_DEBUG必须为true,否则ThinkPHP8不会加载.env文件。
立即学习“PHP免费学习笔记(深入)”;
方法二:确认.env文件位置。它必须放在项目根目录(和index.php同级),不是config/或app/下。
方法三:检查键名格式。DB_PASSWORD=abc123有效,db_password、Db_Password都读不到——必须全大写+下划线。
方法四:终端执行php -r "echo getenv('DB_PASSWORD'); ",输出为空说明系统环境变量没设;再在控制器里加一行dump(env('DB_PASSWORD'));,输出null就说明上面任一条件不满足。
排查MySQL用户host匹配问题
第一步:登录MySQL执行SELECT User, Host FROM mysql.user WHERE User = 'your_user';
PHP 8.5.12 RC 1 候选版修复 BZ2、DOM、PDO、Opcache/JIT 和扩展内存安全问题,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
第二步:比对PHP配置中的DB_HOST值。MySQL把'user'@'localhost'和'user'@'127.0.0.1'当作两个完全不同的用户。ThinkPHP8默认走TCP连接,即使你配DB_HOST=localhost,PDO也可能尝试匹配'user'@'127.0.0.1'。
第三步:若返回结果只有localhost,而你的PHP用的是127.0.0.1连接,就会报1045。解决办法二选一:① 把DB_HOST明确设为localhost(强制走socket);② 运行CREATE USER 'your_user'@'127.0.0.1' IDENTIFIED BY 'xxx'; GRANT ALL PRIVILEGES ON *.* TO 'your_user'@'127.0.0.1'; FLUSH PRIVILEGES;
修复MySQL 8.0+认证插件不兼容
进MySQL命令行执行SELECT user, host, plugin FROM mysql.user WHERE user = 'your_user'; 如果plugin列是caching_sha2_password,且你用的是PHP 7.4之前版本或旧扩展,就会报错The server requested authentication method unknown to the client。
执行ALTER USER 'your_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES; 注意your_user和localhost必须和SELECT查出来的完全一致。
云数据库如阿里云RDS、腾讯云CDB无法修改全局default_authentication_plugin,只能对单个用户执行ALTER USER修复。
绕过框架直连验证
在网站根目录建test_db.php,内容为:
<?php $mysqli = new mysqli('127.0.0.1', 'root', '', 'test_db', 3306); if ($mysqli->connect_error) { die('Connect Error: ' . $mysqli->connect_error); } echo 'OK, MySQL is reachable'; $mysqli->close(); ?>
浏览器访问http://your-site/test_db.php,输出OK, MySQL is reachable才算底层通了。


















