ThinkPHP 6+ 必须用 .env 抽离密钥:根目录放 .env(加.gitignore),APP_KEY=base64:xxx,配置文件中用 env('APP_KEY') 读取;.env 禁放 public/,需确保 Web 根目录为 public/ 且 Nginx 禁止访问;中间件中读密钥需确认加载时机;部署后通过日志验证环境变量是否生效。

ThinkPHP 6+ 怎么用 .env 替换配置文件里的密钥
直接改 config/app.php 或 config/database.php 里写死的 'app_key'、'password',等于把密钥钉在 Git 里——只要仓库公开或被拖库,就全暴露。ThinkPHP 6 起原生支持 .env,必须用它抽离敏感值。
实操分三步:
- 确保项目根目录有
.env文件(不在public/下,且已加进.gitignore) - 在
.env里写:APP_KEY=base64:abcd1234...
(注意base64:前缀不能少,否则 ThinkPHP 不识别为加密密钥) - 配置文件中对应位置改用
Env::get('APP_KEY')或env('APP_KEY')读取(推荐用env(),更轻量)
常见错误:在 .env 里写 APP_KEY=abcd1234 却没加 base64:,结果 php think optimize:config 编译后密钥失效,接口全报 500。
为什么不能把 .env 放进 public/ 目录
public/ 是 Web 服务器直接映射的根路径,任何放在里面的 .env 都可能被 Nginx/Apache 误配导致裸奔——比如没禁掉 .env 的访问规则,请求 https://yoursite.com/.env 就直接返回明文内容。
立即学习“PHP免费学习笔记(深入)”;
正确姿势只有两个:
-
.env必须和think可执行文件同级(即项目根目录),且 Web 服务器 DocumentRoot 指向public/,天然隔绝外部访问 - Nginx 配置里显式禁止:
location ~ /\.(env|git|log|tpl|swoole|lock) { deny all; }
很多线上环境用宝塔或一键脚本部署,会默认把整个项目当网站根目录,这时不手动调 DocumentRoot,.env 就是定时炸弹。
env() 和 Env::get() 在中间件里读不到密钥?
不是函数失效,是加载时机问题:ThinkPHP 默认只在应用初始化早期加载 .env,但如果你在中间件里直接调 env('DB_PASSWORD'),而该中间件又注册在「应用启动前」(比如全局中间件数组开头),此时环境变量还没载入。
安全做法:
- 所有依赖密钥的配置(如数据库密码、Redis 密码)统一收口到
config/database.php等配置文件中,靠框架自动加载机制兜底 - 真要在中间件里动态读,先确认中间件类型:
AppInit类中间件可读;Http类中间件需确保注册顺序在LoadEnv之后 - 临时调试可用
var_dump(getenv('DB_PASSWORD')),但生产环境禁用——getenv()不走 ThinkPHP 的环境变量解析逻辑,无法识别base64:前缀
部署时怎么验证 .env 真生效了
别信“我传上去了”,得看运行时行为。最简单的方法是加一行调试代码到 app/common.php 或入口 public/index.php:
file_put_contents(runtime/log/env_check.log, print_r($_ENV, true), FILE_APPEND);
然后请求一次接口,再看日志里有没有你设的 APP_KEY、REDIS_PASSWORD。重点检查两点:
- 值是否是明文(说明
.env加载成功) - 如果值是
null或空字符串,大概率是.env文件权限不对(Linux 下 Apache 用户没读取权)、或者文件编码含 BOM 头(Windows 记事本保存的 UTF-8-BOM 会导致 ThinkPHP 解析失败)
还有个隐蔽坑:Docker 部署时挂载 .env,但容器内 PHP 进程用户(如 www-data)对挂载路径没有读权限,得在 Dockerfile 里加 chmod 644 /app/.env。



















