生产环境 .env 错误会导致数据库静默 fallback;APP_ENV 必须小写且与 config/ 子目录名严格匹配;CLI 需显式调用 Env::set;敏感字段须用 env() 读取并设默认值;.env 需禁止 Web 访问;修改后必须清空 runtime/config.php;DB_HOST 不可用 localhost;env() 是编译期求值。

生产环境的 .env 文件一旦写错或加载失败,数据库连接会静默 fallback 到默认值(比如空库名、127.0.0.1),导致“No database selected”或连到测试库——这不是配置没生效,而是生效了但内容错了。
APP_ENV 必须小写且与 config/ 子目录严格匹配
ThinkPHP 不认 APP_ENV=production 或 APP_ENV=PROD。它只在 APP_ENV=prod 时加载 config/prod/database.php;若你建的是 config/production/ 目录,框架根本不会进去读。CLI 部署时(如 php think migrate),必须在 think 入口脚本里显式调用 think\Env::set('APP_ENV', 'prod'),不能只靠 .env 里的那一行。
DB_PASSWORD 等敏感字段必须用 getenv() 或 env() 显式读取
如果 config/database.php 里还留着 'password' => 'your_real_password',那这个明文就直接进了 Git 和线上包。正确写法是:
'password' => env('DB_PASSWORD', ''),
注意第二参数不能为空(null)或省略——否则 env() 返回 null,连接器会把 null 当字面量拼进 DSN,报错 SQLSTATE[HY000] [1045] Access denied。同时确保 .env 文件本身不在 Web 可访问路径下(Nginx 要禁止 location ~ /\.env)。
立即学习“PHP免费学习笔记(深入)”;
修改后必须清空 runtime/config.php 才能生效
ThinkPHP 启动时会把所有配置合并后缓存到 runtime/config.php。改完 .env 或 config/prod/database.php 后,不删这个文件,框架永远读旧缓存。执行命令:
php think optimize:config
或者手动删除 runtime/config.php。别只清 runtime/cache/,那个不影响配置加载。
DB_HOST 和 DB_PORT 不能依赖 localhost 解析
生产环境用 DB_HOST=localhost 很危险:MySQL 客户端会尝试走 socket 连接(/tmp/mysql.sock),而容器或云数据库根本没有这个文件。必须写真实 IP 或域名,例如 DB_HOST=db-prod.internal。如果用了端口映射(如 Docker),DB_PORT 也得对应宿主机暴露的端口,不是容器内 3306。
最容易被忽略的一点:TP6/TP8 的 env() 函数在配置文件中是「编译期求值」,不是运行时动态刷新。也就是说,连接建立后,哪怕你中途改了系统环境变量,已创建的 PDO 实例里的密码、host 也不会变——所以长连接、Swoole 场景下,务必确认首次加载时 .env 就已正确读入且无格式错误(比如 BOM、等号空格、单引号漏写)。



















