ThinkPHP 8.0 通过系统环境变量 APP_ENV 加载 .env.dev/.env.test/.env.prod 多环境配置文件,需手动集成 vlucas/phpdotenv 并调用 load() 方法,且必须执行 php think optimize:config 清除配置缓存才能生效。

在 ThinkPHP 8.0 项目中,用 .env 文件区分开发、测试、生产环境配置,避免硬编码导致上线时漏改数据库地址或开启调试模式,必须让 APP_ENV 变量生效且被框架正确识别,否则 config/ 目录下所有环境专用配置文件都不会加载。
准备多环境配置文件结构
在项目根目录(与 app、config、public 同级)新建三个文件:.env.dev、.env.test、.env.prod。每个文件只写当前环境专属变量,不要包含通用配置——通用项统一留在 【.env】 中,它会被所有环境默认加载。
例如 .env.dev 内容为:
APP_DEBUG=true
LOG_LEVEL='debug'
REDIS_HOST=127.0.0.1
立即学习“PHP免费学习笔记(深入)”;
.env.prod 则写:
APP_DEBUG=false
LOG_LEVEL='error'
REDIS_HOST=redis-prod.internal
注意:.env 文件必须保存为 UTF-8 无 BOM 编码,否则 ThinkPHP 8 完全静默忽略,不报错也不加载——这是最常被忽略的致命点。
设置系统级 APP_ENV 变量并验证
ThinkPHP 8 默认读取系统环境变量 APP_ENV 决定加载哪个 .env.* 文件,不是读取 .env 里的 APP_ENV 值。
Windows 用户在 CMD 中执行:
set APP_ENV=dev && php think run
Linux/macOS 用户执行:
APP_ENV=test php think run
启动后访问任意接口,在控制器里加一行:dump(getenv('APP_ENV'));,页面应输出字符串 dev 或 test。如果输出 false 或空字符串,说明系统变量未传入 PHP 进程——常见原因是 Apache/Nginx 没透传变量,或 CLI 启动时未前置设置。
启用多环境自动加载机制
打开 public/index.php,找到 require __DIR__.'/../vendor/autoload.php'; 下方附近位置,插入以下代码:
第一步:确保环境变量已存在
if (!getenv('APP_ENV')) { putenv('APP_ENV=' . ($_SERVER['APP_ENV'] ?? 'production')); }
第二步:强制框架加载对应环境文件
$envFile = __DIR__ . '/../.env.' . getenv('APP_ENV');
if (is_file($envFile)) {
Dotenv\Dotenv::createImmutable(__DIR__ . '/..', basename($envFile))->load();
}
这一步必须做:ThinkPHP 8 原生只加载 .env,不支持自动匹配 .env.*,必须手动引入 vlucas/phpdotenv 并指定文件名,否则 .env.dev 等文件永远不生效。
第三步:确认 vendor/autoload.php 已加载 dotenv 类库
若提示 Class 'Dotenv\Dotenv' not found,请先执行:composer require vlucas/phpdotenv
在 database.php 中按环境动态配置数据库
方法一:直接使用 env() 函数读取
打开 config/database.php,在 'connections' → 'mysql' 数组内,把 'hostname' 改为:'hostname' => env('DB_HOST', '127.0.0.1'),;同理设置 'database'、'username'、'password'。
方法二:用条件判断加载不同配置块(更清晰)
在 database.php 顶部加:
$env = env('APP_ENV', 'production');
switch ($env) {
case 'dev': $dbConfig = ['hostname'=>'localhost','database'=>'tp_dev']; break;
case 'test': $dbConfig = ['hostname'=>'10.0.2.10','database'=>'tp_test']; break;
default: $dbConfig = ['hostname'=>'db-prod','database'=>'tp_prod'];
}
然后在 connections.mysql 中直接写:'hostname' => $dbConfig['hostname'], 'database' => $dbConfig['database'],
注意:不要在 switch 外部直接写 $dbConfig['hostname'],PHP 会报 undefined variable 错误。
清除缓存并验证环境变量是否注入成功
执行命令:php think optimize:config
这一步不可跳过:ThinkPHP 8 的配置是缓存化的,即使 .env.* 和 database.php 全部改对,不执行此命令,框架仍从 runtime/cache/config 下读旧值。
验证是否生效:在控制器中写
dump(env('DB_HOST'));
dump(config('database.connections.mysql.hostname'));
两个 dump 输出必须一致,且等于你当前 APP_ENV 对应 .env.* 文件中 DB_HOST 的值。如果第一个有值第二个为空,说明 config/database.php 没正确引用 env();如果两个都为空,说明 .env.* 文件没被加载或 APP_ENV 设置错误。



















