Webman默认不自动加载.env文件,必须在start.php顶部显式调用Dotenv::createImmutable(__DIR__)->load(),且需早于任何config()调用,否则env()读取为空或默认值。

Webman 默认不自动加载 .env 文件,必须显式引入环境变量解析逻辑,否则 env() 或 getenv() 读到的全是 null 或默认值。
为什么 .env 文件写好了却完全没生效
根本原因是 Webman(包括底层 Workerman)本身不内置 .env 解析能力。你看到的 env() 函数,要么来自第三方插件(如 majie721/webmanenv),要么是你自己用 vlucas/phpdotenv 手动加载的 —— 框架启动流程里没有这一环。
常见错误现象:
-
config('app.debug')始终返回默认值,不随.env中APP_DEBUG=true变化 - 数据库配置全为空,
getenv('DB_HOST')返回false或null - 打包成
.phar后彻底失效(因为.env被排除在包外,且未在运行时重新加载)
用 vlucas/phpdotenv 手动加载 .env
这是最通用、兼容性最好的方式,适用于所有 Webman 版本(v1.x / v2.x),也适配 .phar 场景。
实操建议:
- 执行
composer require vlucas/phpdotenv - 在
start.php最顶部(必须在任何 config() 调用之前)加入:
use Dotenv\Dotenv; $dotenv = Dotenv::createImmutable(__DIR__); $dotenv->load();
注意点:
-
__DIR__表示从项目根目录找.env;若文件放在别处(如config/.env),需传入完整路径:Dotenv::createImmutable(__DIR__ . '/config') - 不要用
createUnsafeImmutable(),它会覆盖已存在的系统环境变量,CI/容器部署时容易出问题 - 开发期可加
->safeLoad()避免因.env缺失报错,但上线前建议确保文件存在
命令行传参切换环境(如 -e APP_ENV=PROD)
这个需求本质是「运行时覆盖 .env 值」,不是替换整个文件。关键在于:参数要进 putenv(),且必须早于 Dotenv::load() 执行。
Webman 2.2.0版本强化了 TCP/UDP 服务支持,优化路由组管理,并增强异步任务处理能力。结合协程与连接池技术,Webman 能轻松应对高并发场景,适用于网站、接口服务、即时通讯、物联网及游戏开发,兼具高性能、灵活扩展与稳定可靠,是多场景 PHP 服务开发的理想选择。
正确顺序(写在 start.php 开头):
- 遍历
$argv,识别-e参数后紧跟的键值对(如APP_ENV=PROD) - 调用
putenv('APP_ENV=PROD'),让后续getenv()和Dotenv都能感知 - 再执行
Dotenv::load()—— 此时Dotenv会跳过已存在的环境变量,只加载缺失项
示例片段:
foreach ($argv as $i => $arg) {
if ($arg === '-e' && isset($argv[$i + 1]) && str_contains($argv[$i + 1], '=')) {
putenv($argv[$i + 1]);
}
}
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();
启动命令就变成:
php start.php start -e APP_ENV=PROD
.phar 打包后读不到 .env 怎么办
打包工具(如 webman/console 插件)默认把 .env 加入 exclude_files 列表,导致它根本不在 .phar 包内。而 Dotenv::createImmutable(__DIR__) 查的是 .phar 所在目录,不是包内路径。
两个可靠解法:
-
删掉
exclude_files中的'.env':修改config/plugin/webman/console/app.php,从['.env', ...]里移除它,让.env进包;然后改用Dotenv::createMutable(__DIR__)并指定phar://路径(需确认 PHP 支持 Phar 流封装) -
更推荐:不打包
.env,靠外部挂载:把.env放在.phar同级目录,启动时用Dotenv::createImmutable(dirname($_SERVER['SCRIPT_FILENAME']))显式指向该位置
后者更安全 —— 避免敏感配置硬编码进二进制包,也符合十二要素应用原则。
真正容易被忽略的是:无论用哪种方式,Dotenv::load() 必须在 config() 之前执行,且不能被任何条件分支包裹;一旦错过这个时机,后续所有基于 env() 的配置都已固化,改环境变量也无效。

















