[译]Laravel 5.0 之运行环境及环境变量

本文译自 Matt Stauffer系列文章.


如果你关注我的博客有段时间了,那你应该曾经见过我在 Laravel 环境检测问题上的各种尝试,特别使用环境变量进行检测这方面。例子

感谢 Laravel 5, 它极大地简化了环境检测环节。在 4.x 版的时候,你要创建多个基于运行环境名称的环境配置文件(比如 .env.php, .env.local.php 等)。老实说,我从来用过这个功能。但我觉得理论上你应该会把所有环境配置文件提交到代码库。但由于我们从来不提交任何环境配置文件,所以这种区分环境的手段毫无用处,而且它还会造成环境配置文件的延迟加载,因为只有检测到运行于什么环境之后,它才能进行相应的配置文件加载。

PHP dotenv 介绍

Laravel 5.0 其实也没做什么特别的创新,它只是使用了 PHP dotenv, 一个从单一 .env 文件中加载环境配置的第三方库。

新版本的 Laravel 初始框架包含一个默认的 .env.example 文件,这个文件暂时看起来长这样:

APP_ENV=local
APP_KEY=SomeRandomString
DB_USERNAME=homestead
DB_PASSWORD=homestead

要使用这个功能,只需要复制这个文件并重命名为 .env (类似 wordpress 的 wp-config-sample.php). 为什么不直接重命名原始文件而是先复制再重命名呢?下面马上就要说到了。

接下来,就可以编辑 APP_ENV 的值来指定运行环境了。这是在 Laravel 5.0 中我们指定应用运行环境名称的主要手段。可以看一下 bootstrap/environment.php 里最新的环境监测代码,它非常简单:

$env = $app->detectEnvironment(function()
{
    return getenv('APP_ENV') ?: 'production';
});

这么简单,多美好的一件事!

自定义环境配置文件

现在回答刚才的那个问题:为什么不直接重命名 .env.example 这个原始文件呢?想象一下,假设你的应用要定义 10 个环境变量,怎么确保它被部署到不同运行环境下时都能保证定义了这些环境变量呢?当然,你可以在捡测到环境变量没定义的时候进行容错处理。但更好的处理方式还是定义这些变量。

这种情况下,你打算在那里做每个部署的 .env 文件的变量配置说明呢?一种方式:你可以写在 readme 文件里。更好的办法是更新 .env.example 文件,在里面加上你的应用需要定义的环境变量以及相应的注释。

如此一来,如果在应用的每个部署都定义 10 个环境变量,那就把这 10 个环境变量加到你的 .env.example 文件里,指定默认值。这个默认文件会提交到你的版本管理工具中。然后每次进行部署时只要执行 cp .env.example .env 命令,然后对 .env 中的变量值进行修改即可。

变量引用

如果需要了解更多,可以查看 PHP dotenv 的文档,但我可以告诉你一个最有用的技巧:一个已定义的环境变量是可以在后续的环境变量值中引用的。看一下他们的说明文档中的例子:

BASE_DIR=/var/webroot/project-root
CACHE_DIR=$BASE_DIR/cache
LOG_DIR=$BASE_DIR/logs

很直观。

指定必须定义的变量

某些变量是系统运行不可或缺的。对于这种情况,我们可以指定他们是必须定义的,而不是等应用开始用到这些变量时才发现没有定义而造成崩溃:

Dotenv::required('DB_USERNAME');
// 或者
Dotenv::required(['DB_HOST', 'DB_NAME', 'DB_USERNAME', 'DB_PASSWORD']);

通过 Dotenv::required() 方法指定即可,参数可以是单个字符串或者是字符串数组,每个字符串代表一个环境变量名。如果某个环境变量没有定义,系统会抛出一个 RuntimeException.

写在最后

简单,易用,强大。而且这个新特性让我之前所有关于 Laravel 框架运行环境检测的文章、实践和抱怨都失去了意义。如今你可以很轻松地定义自己的运行环境名称和环境变量,而且是在单一的一个文件中,以一种可预期的,始终一致的方式来实现。