Laravel 和 Lumen 中通过环境变量配置对应的 env 文件

前情提要

一般程序至少都会有开发、测试、生产三个环境。我一般习惯有.env、.env.test、.env.production 三个文件

如果每次被动的去相应的环境修改env配置的话,是一件很麻烦的事情

nginx配置

# example.conf
# 见 fastcgi_param 参数
location ~ \.php$ {
    fastcgi_pass   php72:9000;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param  APP_ENV production; 
}

lumen下的使用

# bootstrap/app.php
require_once __DIR__.'/../vendor/autoload.php';

# 配置env文件
$environment = env('APP_ENV', false);
$environment_file = !env('APP_ENV', false) ? '.env' : ".env.$environment";
(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
    dirname(__DIR__), $environment_file
))->bootstrap();

laravel下的使用

laravel下使用无需进行配置, 具体原因见如下分析

原理分析

其实 lumen 和 laravel 加载 env 的配置都差不多,主要可见 Dotenv\Dotenv 类, 从而读取配置信息

lumen中依赖的启动方式在主要在app.php

(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
    dirname(__DIR__)
))->bootstrap();

我们可以看到 加载 env file 和 env path,是直接进行初始化的

public function __construct($path, $name = null)
{
    $this->filePath = $path;
    $this->fileName = $name;
}

我们再来看下laravel的

# 启动器
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

# 这里实现一个单例: 重要之处
$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);

完成后返回一个app, 在public/index.php

它会先从容器中解析出类实例

Illuminate\Contracts\Http\Kernel::class
对应
App\Http\Kernel::class

解析后

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

# 执行handle方法
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

handle方法是怎么来的呢,见App\Http\Kernel::class

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel{
    ...
}

我们发现在 Kernel 没有handle这个方法,所以这里执行的handle是父方法的handle : Illuminate\Foundation\Http\Kernel

# step1
$response = $this->sendRequestThroughRouter($request);

# step2
$this->bootstrap();

# step3
$this->app->bootstrapWith($this->bootstrappers());

# 注:
$this->bootstrappers = [
    'Illuminate\Foundation\Bootstrap\DetectEnvironment',
    'Illuminate\Foundation\Bootstrap\LoadConfiguration',
    'Illuminate\Foundation\Bootstrap\ConfigureLogging',
    'Illuminate\Foundation\Bootstrap\HandleExceptions',
    'Illuminate\Foundation\Bootstrap\RegisterFacades',
    'Illuminate\Foundation\Bootstrap\RegisterProviders',
    'Illuminate\Foundation\Bootstrap\BootProviders'
];

所以得到了我们的DetectEnvironment

从而具体的解析方法见

protected function checkForSpecificEnvironmentFile($app)
{
    if (! env('APP_ENV')) {
        return;
    }

    # $app->environmentFile() : .env
    # env('APP_ENV') = 'production'
    $file = $app->environmentFile().'.'.env('APP_ENV');

    if (file_exists($app->environmentPath().'/'.$file)) {
        $app->loadEnvironmentFrom($file);
    }
}

但我们在nginx中配置了 app_env的值的时候,它会自动进行拼接得到这个env file, 最后的结果为 .env.production

命令行下的使用

# 执行artisan命令
APP_ENV=production && php artisan test

参考文章:

laravel中env文件的加载: www.jianshu.com/p/0370072a6023

Laravel源码入门-启动引导过程:my.oschina.net/zhmsong/blog/900617

通过nginx的fastcgi_param来设置环境变量:www.cnblogs.com/gantoday/p/7465097...

Laravel 启动流程分析 (代码全流程):
博客:Laravel 启动流程分析 (代码全流程)

make使用文档: 服务容器《Laravel 7 中文文档》

本作品采用《CC 协议》,转载必须注明作者和本文链接
每天3小时...加油
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 1

其实感觉在发布哪里做手脚比该源代码这种方法更好吧。 也是不同的版本 然后发布不同的环境更改去给不同环境的 .env 做不同mv操作。。

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!