Laravel 和 Lumen 中通過環境變數配置對應的 env 檔案

surest發表於2020-05-06

前情提要

一般程式至少都會有開發、測試、生產三個環境。我一般習慣有.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小時...加油

相關文章