dotenv 在生产中需要 .env 文件
Posted
技术标签:
【中文标题】dotenv 在生产中需要 .env 文件【英文标题】:dotenv requires .env file on production 【发布时间】:2015-08-19 03:39:20 【问题描述】:我在 php 中使用 dotenv 来管理环境设置(不是 lavarel,但我标记了它,因为 lavarel 也使用 dotenv)
我已将 .env 从代码库中排除,并为所有其他合作者添加了 .env.example
dotenv的github页面上:
phpdotenv 是为开发环境而设计的,一般不应该在生产环境中使用。在生产环境中,应该设置实际的环境变量,这样就不会在每个请求上加载 .env 文件的开销。这可以通过使用 Vagrant、chef 或 Puppet 等工具的自动化部署过程来实现,也可以使用 Pagodabox 和 Heroku 等云主机手动设置。
我不明白的是,我得到了以下异常:
PHP Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Dotenv: Environment file .env not found or not readable.
这与文档中所说的“应设置实际的环境变量,以便在每个请求上没有加载 .env 文件的开销”相矛盾。
所以问题是 dotenv 是否有任何原因引发该异常和/或我错过了什么?首先,与其他 dotenv 库(ruby)相比,行为是不同的
我可以轻松解决这个不太好的解决方案:
if(getenv('APPLICATION_ENV') !== 'production') /* or staging */
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
我认为最好的解决方案,但我认为 dotenv 应该处理这个问题。
$dotenv = new Dotenv\Dotenv(__DIR__);
//Check if file exists the same way as dotenv does it
//See classes DotEnv\DotEnv and DotEnv\Loader
//$filePath = $dotenv->getFilePath(__DIR__);
//This method is protected so extract code from method (see below)
$filePath = rtrim(__DIR__, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR . '.env';
//both calls are cached so (almost) no performance loss
if(is_file($filePath) && is_readable($filePath))
$dotenv->load();
【问题讨论】:
如果你不在生产服务器上使用 .env ,那么你如何设置你的环境变量呢? 【参考方案1】:Dotenv 是围绕一个想法构建的,即它将仅用于开发环境。因此,它总是期望存在.env
文件。
您不喜欢的解决方案是使用 Dotenv 的推荐方式。看来,它won't change in near future。项目问题跟踪器中的相关讨论:https://github.com/vlucas/phpdotenv/issues/63#issuecomment-74561880
请注意,Mark offers 有一种适用于生产/暂存环境的好方法,它跳过文件加载,但不验证
$dotenv = new Dotenv\Dotenv();
if(getenv('APP_ENV') === 'development')
$dotenv->load(__DIR__);
$dotenv->required('OTHER_VAR');
【讨论】:
啊,我可以使用$dotenv->required()
,它可以以任何方式工作,这很好。我猜getenv('APP_ENV');
更安全?我想我会选择适合当前项目的文件检查。谢谢!
@SanderVisser 你说getenv('APP_ENV')
更安全是什么意思?
它会阻止在生产环境中加载 .env 文件,即使它存在。
当我想到。开发环境是使用 vagrant 和 puppet 构建的,因此可以使用一些合理的开发默认值来跳过 dotenv 的一次性步骤。这就是我选择文件检查方法的原因。但将这两种方法结合起来并不是什么大问题【参考方案2】:
如果您在创建 APP_ENV 变量时遇到问题,此代码会更简单:
$dotenv = new Dotenv\Dotenv(__DIR__);
if(file_exists(".env"))
$dotenv->load();
【讨论】:
【参考方案3】:也对此进行了调查,我目前的解决方案是使用 Lumen's way(截至 2016 年 6 月 6 日),即 suggested in a discussion:
try
(new Dotenv\Dotenv(__DIR__.'/../'))->load();
catch (Dotenv\Exception\InvalidPathException $e)
//
如果需要,您仍然可以进行一些额外的异常处理(例如,使用默认值或进行一些验证。
【讨论】:
这违背了“没有在每个请求上加载 .env 文件的开销”的目的 @MassimilianoArione 使用DotEnv
at all 会产生在每个请求上加载.env
文件的开销,因此您的评论实际上适用于使用@987654326 的整个前提@,而不仅仅是这个答案。以上是关于dotenv 在生产中需要 .env 文件的主要内容,如果未能解决你的问题,请参考以下文章
process.env.NODE_ENV === "开发" 即使在生产中
您应该使用 Babel 配置中的 `env` 部分在生产中禁用 react-transform-hmr