ThinkPHP6远程连接MySQL必须填公网IP而非localhost或域名;.env优先级高于database.php,DB_HOST须设为MySQL服务器公网IPv4地址(如203.124.55.88),密码含特殊字符需URL编码,且params中须显式保留PDO::ATTR_EMULATE_PREPARES=>false。

直接填公网 IP,别用 localhost 或域名;.env 优先级高于 config/database.php,改错地方就白忙活。
远程 MySQL 服务端必须放开的三件事
PHP 连不上远程 MySQL,90% 的问题出在服务端配置没到位,不是 PHP 写错了。
-
bind-address = 0.0.0.0(或具体 PHP 服务器 IP),不能是127.0.0.1;改完重启 MySQL:sudo systemctl restart mysql - 创建带来源限制的用户,例如
CREATE USER 'tp6_app'@'203.124.55.88' IDENTIFIED BY 'strong_pwd_2026';,然后GRANT SELECT,INSERT,UPDATE ON mydb.* TO 'tp6_app'@'203.124.55.88'; FLUSH PRIVILEGES; - 云服务商安全组 / 防火墙必须放行 TCP 3306 端口,源 IP 填 PHP 服务器的**出口公网 IP**(不是内网 IP),腾讯云填“安全组”,GCP 填“VPC 防火墙规则”
验证是否通:在 PHP 服务器上执行 nc -zv 203.124.55.88 3306,返回 succeeded 才算过第一关。
ThinkPHP6 配置文件里怎么写 host?
填 127.0.0.1 是本地回环,填 localhost 会走 Unix socket,填域名要走 DNS 解析——这三者在远程场景下全错。
立即学习“PHP免费学习笔记(深入)”;
- 必须用 MySQL 服务器的**公网 IPv4 地址**,例如
'hostname' => '203.124.55.88' - 如果启用了
.env,则必须写DB_HOST=203.124.55.88;改了config/database.php却不生效,大概率是.env里还存着旧的DB_HOST=localhost - 密码含
@、/、:等字符时,必须 URL 编码,例如pa@ss/word→pa%40ss%2Fword,否则 PDO 初始化直接报SQLSTATE[HY000] [1045]
PDO 连接参数不设对,LIKE 和中文就出事
ThinkPHP 默认已设 PDO::ATTR_EMULATE_PREPARES => false,但如果你在 params 里自定义了参数,一不小心就会覆盖掉它。
- 务必显式保留该选项:
'params' => [\PDO::ATTR_EMULATE_PREPARES => false],否则where('name', 'like', '%张%')可能被错误转义 - 推荐加初始化命令:
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",避免连上后多一次SET NAMES请求,减少 round-trip 延迟 - 不要设
PDO::ATTR_PERSISTENT => true上生产——长连接在负载均衡或容器漂移场景下容易导致连接泄漏或状态残留
连接失败时先别查 PHP,查网络和权限
看到 SQLSTATE[HY000] [2002] Connection refused 或 [2003] Can't connect to MySQL server,别急着翻 ThinkPHP 文档。
- 先确认 MySQL 进程在跑:
systemctl is-active mysql - 再确认端口监听的是
0.0.0.0:3306,不是127.0.0.1:3306:ss -tlnp | grep :3306 - 用
mysql -h 203.124.55.88 -u tp6_app -p从 PHP 服务器手动连一次,绕过框架验证权限和网络 - 错误日志看
/var/log/mysql/error.log,里面常有“Access denied for user … using password: YES”这种提示,说明用户授权没生效或密码不对
最易忽略的是:云服务器开了防火墙,但忘了配安全组;或者本地开发测试用的 127.0.0.1 直接上线,一部署就崩。



















