env() 在 config/autoload/ 中返回 false 的根本原因是配置文件加载早于 Dotenv 解析,此时 $_ENV 和 getenv() 仍为空;正确做法是在 Provider boot()、Command 或 Listener 中读取,且需注意类型转换与 PHP variables_order 设置。

env() 在 config/autoload/ 里返回 false 或默认值
这是最常见现象:你在 config/autoload/database.php 里写 env('DB_HOST', '127.0.0.1'),但启动后连不上数据库,var_dump(env('DB_HOST')) 输出 false。根本原因不是 .env 文件没写对,而是配置文件加载时机早于 Dotenv 解析完成。
Hyperf 启动时先扫描 config/autoload/ 下所有 PHP 文件(按字母序),此时 $_ENV 和 getenv() 还是空的——.env 要到容器初始化后期才被 DotenvLoader 加载。
- 别在
config/autoload/*.php里直接调用env()做关键配置,尤其不能用于数据库、Redis 等组件初始化参数 - 临时验证方法:在配置文件顶部加
var_dump(getenv('DB_HOST'));,如果输出false,就坐实了加载时机问题 - 真正安全的读取位置是服务提供者(
Provider)的boot()方法、命令类(Command)或监听器(Listener)中
运行 php bin/hyperf.php config:show --key=database.default 显示来源却是 config/autoload/
说明你写的 env('DB_HOST') 已被当成字符串字面量处理了,或者被低优先级配置覆盖。Hyperf 的配置合并优先级是:系统环境变量 > .env > config/autoload/*.php,但前提是 .env 真的被成功加载且没被跳过。
- 执行
php bin/hyperf.php env确认当前APP_ENV值,比如输出dev却实际想用prod,会导致config/autoload/prod/下的配置没生效 - 检查
.env文件是否真在项目根目录(BASE_PATH),而不是子目录或拼错成.env.local—— Hyperf 默认只认.env - 运行
php bin/hyperf.php config:show --all | grep DB_HOST,看最终值来自哪一层;如果来源是config/autoload/database.php,说明env()没起作用,退回到硬编码默认值了
PHP 的 variables_order 不含 E 导致 getenv() 失效
即使 .env 被 Dotenv 正确解析,如果 PHP 自身禁用了 $_ENV,env() 函数也会永远返回 false。这不是 Hyperf 的 bug,而是 PHP 运行时限制。
- 新建一个
test-env.php,内容为,直接 CLI 执行看是否输出 - 若输出
false,检查php.ini中variables_order是否包含E(如"EGPCS");不含则需修改并重启 PHP-FPM 或 Swoole 进程 - Docker 容器内常忽略这点:基础镜像可能默认删掉
E,需在Dockerfile中显式设置variables_order = "EGPCS" - 别依赖
$_SERVER['DB_HOST'],它和getenv()是两套机制,$_SERVER不会自动同步.env变量
配置类型未转换引发服务启动失败
Hyperf 3.x 对配置类型校验变严,env('SERVER_HTTP_PORT') 返回的是字符串 "9501",但 server.php 的 port 字段要求整型,不转换会直接报错退出。
- 所有数字型配置必须显式强转:
'port' => (int)env('SERVER_HTTP_PORT', 9501) - 布尔型不能靠字符串比较:
'debug' => filter_var(env('APP_DEBUG', 'false'), FILTER_VALIDATE_BOOLEAN) - 数组嵌套建议用 PHP 配置而非 YAML:YAML 解析失败时静默丢弃,PHP 报错更明确
- 敏感字段(如密码)不要写进
.env,留空DB_PASSWORD=,靠系统环境变量注入,避免泄露风险
最易被忽略的一点:改完 .env 或配置文件后,必须重启 Hyperf 进程——协程服务不会自动重载环境变量,runtime/container/ 缓存也不会帮你刷新 getenv() 的底层状态。











