根本原因是ThinkPHP在CLI下默认不加载.env且不合并extra配置,导致config()读取空缓存或fallback值;需确认工作目录、启用env_file、手动load()、检查extra声明、清缓存并用Env::get()替代getenv()。

CLI 模式下 config() 返回 null 或旧值
根本原因是 ThinkPHP 在 CLI 下默认不加载 .env,也不自动合并 extra 配置,导致 config() 查的是初始化时的空缓存或 fallback 值。不是函数坏了,是环境没搭对。
- 确认当前是否在项目根目录执行命令:必须
cd /path/to/project && php think xxx,否则Dotenv::createImmutable(__DIR__)解析路径失败 - 检查
config/app.php中'env_file' => '.env'是否存在且未被注释;TP6.1+ 内置think-env时该配置才生效 - 在入口文件
think末尾手动补加载逻辑(TP6/TP8 均适用):if (PHP_SAPI === 'cli') {<br> \think\facade\Env::load();<br>} - 若用
Dotenv手动加载,别漏掉safeLoad()——它会跳过权限错误或格式异常的行,比load()更健壮
数据库配置在定时任务里连不上
Config::get('database.hostname') 还是 127.0.0.1?大概率是 Env::get('DB_HOST') 没读到值,而框架 fallback 到了默认值。Web 能连上不代表 CLI 能连。
- 所有敏感字段(
DB_PASS、REDIS_PASSWORD等)必须走Env::get(),绝不能硬编码在 PHP 配置文件里 - 在命令类的
handle()开头加一行调试:var_dump($_ENV['DB_HOST'] ?? 'not set', \think\facade\Env::get('DB_HOST', 'fallback')); - 如果
$_ENV为空但Env::get()有值,说明.env加载成功;反之则要检查.env文件权限(CLI 用户能否读)、BOM 头、是否被 git 忽略但实际不存在 - 生产环境用 KMS 解密时,务必把解密逻辑包在
Env::get('DB_PASS') ?: decryptFromKMS()里,并 catch 异常,避免 config 加载中断导致整个命令失败
自定义配置(如 wechat.php)在 CLI 下读不到
extra 配置不会因 CLI 模式被跳过,但加载前提是它已被声明且路径正确。没声明 = 不加载 = config('wechat.appid') 返回 null。
- 检查
config/app.php的'extra' => ['wechat']是否存在,键名必须是字符串数组,不能是'wechat.php'或['wechat.php'] - 确认
config/wechat.php文件真实存在,且返回的是合法 PHP 数组(无语法错误、无 BOM、无echo输出) - 多应用模式下,CLI 命令默认走根应用配置,子应用(如
app/admin/config/wechat.php)不会自动合并——除非你在命令中显式切换应用:\think\App::instance()->switchApp('admin'); - 修改后必须清缓存:
php think clear:config或手动删掉runtime/config.php;OPcache 也要重载(sudo pkill -f "php-fpm"或opcache_reset())
为什么 config('app.debug') 是 true,但 .env 里 APP_DEBUG=false?
因为 CLI 模式下 .env 没加载,框架退回到 PHP 的 $_ENV 或 getenv(),而这两个在 CLI 中默认为空。你看到的 true 很可能是代码里硬写的 fallback,不是真实环境值。
立即学习“PHP免费学习笔记(深入)”;
- 别信
phpinfo()里显示的$_ENV,CLI 下它基本不可靠;以Env::get('APP_DEBUG')输出为准 - 在 systemd 或 supervisor 启动 CLI 服务时,必须显式注入环境变量:
Environment="APP_DEBUG=0"<br>EnvironmentFile=/path/to/project/.env
- 运行
php -r "print_r(getenv());"查看当前 CLI 环境变量快照,对比.env内容,快速定位缺失项 - 如果非要让 CLI 继承 Web 的环境变量(不推荐),可在
think入口加:putenv('APP_DEBUG=' . $_SERVER['APP_DEBUG'] ?? '0');,但前提是 Web 环境已由 Web 服务器注入
Env::load() + 用 Env::get() 替代 getenv() + 修改后清 runtime 缓存。



















