背景
- 其实这个过程分为了好几个阶段
需求阶段1
- 受制于Laravel的一丢丢限制,需要在不同的域名下,使用不同的配置,故产生需求。
需求阶段2
- 在反向的情况下需要使用不同的配置,应该是属于需求阶段1的需求扩展。
需求阶段3
- 在开发场景下,在不同的电脑上每次开发,需要同步各处的env,但是env配置是不加入git库的,导致一时间无法获取正确的env配置,消耗过多时间去操作。
- 尤其是其中一台电脑很久没有开机过了,导致配置变更过大,特别是新增的env配置,很容易忽略,由此产生了env同步的需求。
过程
- 万般无奈,在网上发了求助帖,各种复杂方案都有,由于开发项目env配置的低敏感度,加上均为私人库,最后获得了一个指定env配置的方案。
方案特点
- 本地快速切换:改一下别名即可(生产环境也支持,一般不会去切换而已)
- 兼容框架原有的
.env
模式:只要代码不动,就是原有模式 - 生产环境无需改造:不影响生产环境的运行,使用只要改代码即可
- 支持多种模式:目前支持指定模式、域名模式、反代模式三种模式
特别说明
- 本方案只是一个偷懒的方案,并不是什么完美的解决方案,所以不喜勿喷,如果想要更好效果可以参考
Apollo
、Nacos
等其他方案!!!
代码与说明
- 在
bootstrap/
文件夹下新建文件env.php
,代码如下
<?php
// 环境处理
/* @var Illuminate\Foundation\Application $app */
if (is_file(__DIR__ . '/../.env.local_set')) {
// 本地指定形式
$suffix = '.local.' . file_get_contents(__DIR__ . '/../.env.local_set');
} else {
// 非Console环境下
$suffix = '';
if (!$app->runningInConsole()) {
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
// 反代形式
$suffix = '.' . 'forwarded';
} else {
// 域名形式
if (empty($_SERVER['SERVER_NAME'])) {
die('[error] no host');
}
$suffix = '.' . $_SERVER['SERVER_NAME'];
}
}
}
// 判断文件存在并写入环境配置
if (is_file(__DIR__ . '/../.env' . $suffix)) {
$app->loadEnvironmentFrom('.env' . $suffix);
}
- 修改文件
bootstrap/app.php
// 原先的代码
$app = new Illuminate\Foundation\Application(
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
// 新增的代码,仅需一行即可
require_once __DIR__ . '/env.php'; // 引入多env配置文件
- 在根目录新建
.env.local_set
文件,下面会说明。 - 在根目录新建
.env.local_set.example
文件,作用类似于.env.example
。 - 最后修改根目录中的
.gitignore
文件,在.env
的最下面添加如下的几行代码 - 这块的代码可以根据自己的需求自定义
.env.*
!.env.example
!.env.local_set.example
!.env.local.*
- 如上示例代码所示,生产环境下,可以添加
.env
、.env.域名
、.env.forwarded
(反向代理专用),该类env文件均不会被添加到git库中。 - 新建的
.env.local.*
(*代表任意字符,用于识别环境,可以是电脑别名、代号、生产环境、测试环境等等任意字符),该类文件均会被添加到git库。 - 新建的
.env.local_set
是用于.env.local.*
的指定环境,里面的内容写上.env.local.*
中的*
即可。 - 代码优先级,
指定环境
>反向代理环境
>多域名环境
>普通环境(即加载默认的**.env**)
。 - 其中
指定环境
下,命令行模式会使用指定环境
下的env文件,其他情况下会使用正常的.env
文件,此处考虑到服务器上跑的任务调度,队列等服务只在一台服务器上处理。 - 有新的指定env引入,只需要新建对应的
.env.local.*
并提交即可。 - Enjoy it.
ThinkPHP教程
- 由于ThinkPHP文档里已经写了,有专用函数用于设置ENV,故改造起来很简单。这边只写出了改造文件的教程,其他参考Laravel的教程即可。
- 根目录新建
env.php
文件
<?php
/* @var think\App $app */
// 环境处理
if (is_file(__DIR__ . '/.env.local_set')) {
// 本地指定形式
$envName = 'local.' . file_get_contents(__DIR__ . '/.env.local_set');
} else {
// 非Console环境下
$envName = '';
if (!$app->runningInConsole()) {
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
// 反代形式
$envName = 'forwarded';
} else {
// 域名形式
if (empty($_SERVER['SERVER_NAME'])) {
die('[error] no host');
}
$envName = $_SERVER['SERVER_NAME'];
}
}
}
if (is_file(__DIR__ . '/.env.' . $envName)) {
$app->setEnvName($envName);
}
- 修改
public/index.php
文件
...
// 执行HTTP应用并响应
$app = new App();
require __DIR__ . '/../env.php'; // 引入多env配置文件
$http = $app->http;
// $http = (new App())->http;
...
- 修改根目录
think
文件
...
// 应用初始化
$app = new App();
require __DIR__ . '/env.php'; // 引入多env配置文件
$app->console->run();
// (new App())->console->run();
示例
线上环境多域名及反代示例
- 现有生产环境域名
www.abc.com
和生产环境域名www.def.com
,以及反代环境www.xyz.com
。 - 在服务器上新建
.env.www.abc.com
、.env.www.def.com
文件,此时使用相应的文件访问时,使用的即为对应的配置文件。如果域名对应的文件不存在,则默认加载.env
文件。
指定环境示例
- 现有本地开发环境
dev
和本地开发环境test
。 - 新建
.env.local.dev
和.env.local.test
,并提交到git库。 - 在
.env.local_set
文件中将里面的内容改为dev
,此时项目的env文件使用的是.env.local.dev
文件,如果需要切换到test
,在.env.local_set
文件中将里面的内容改为test
即可。 - 如果无
.env.local_set
文件,或者.env.local_set
文件里无内容,或者.env.local_set
的内容无对应匹配文件,则默认加载.env
文件。
版权属于:塵世不再
本文链接:https://www.leeay.com/archives/107/
所有文章均采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。 您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
如果博客部分文章出现空白或异常,请留言或者联系博主修复。