不同公司所制定的系統環境規範都有所不同。
比方說環境變數的設定,敝公司的規範如下:
- 不設定系統環境變數
/etc/environment
,而是使用檔案載入
- 系統人員將會把檔案放在
/path/to/.env
- 部分的環境設定系統人員不清楚,會由開發人員設定。換句話說,還有另一個 env 是跟著專案跑的。
上述會有幾個要點要注意:
- Laravel 預設只有載入
/path/to/project/.env
,而上面的規範,還會多載 /path/to/.env
- 系統人員設定的
.env
開發人員不能隨意覆蓋
很直接的 Workaround
最一開始,使用最蠢的 workaround,直接修改 bootstrap/app.php
:
if (file_exists('/path/to/.env')) { (new Dotenv\Dotenv('/path/to'))->load(); }
return $app;
|
簡單,也很有效。只是有點不明顯,在重建環境時,很容易忘了這件事。
自定義新的 Bootstrapper
分析 bootstrap 流程有提到原本的 .env
如何載入,我們想辦法來客製化這個流程,讓載 env 也成為 Laravel Bootstrap 的流程之一。
一個直接做法是,自己寫一個 bootstrap:
<?php
namespace App\Bootstrap;
use Dotenv\Dotenv; use Illuminate\Contracts\Foundation\Application;
class CustomizeLoadEnvironmentVariables { public function bootstrap(Application $app) { if (file_exists('/path/to/.env')) { (new Dotenv('/path/to'))->load(); } } }
|
然後在 Http Kernel 覆寫 bootstrappers 屬性即可:
protected $bootstrappers = [ App\Bootstrap\CustomizeLoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class, ];
|
覆寫 Bootstrapper
自定義新的 Bootstrapper 的缺點是,會需要覆寫一個修改內容不多的 bootstrappers,某種程度這也算是 copy & paste 的產物,這是不符合 DRY 原則的。
這裡還有另一個做法則是拿原有的來覆寫:
<?php
namespace App\Bootstrap;
use Dotenv\Dotenv; use Illuminate\Contracts\Foundation\Application; use Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables as BaseLoadEnvironmentVariables;
class LoadEnvironmentVariables extends BaseLoadEnvironmentVariables { public function bootstrap(Application $app) { if (file_exists('/path/to/.env')) { (new Dotenv('/path/to'))->load(); }
parent::bootstrap($app); } }
|
接著在 bootstrap/app.php
綁定這個實作即可:
$app->singleton( Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, App\Bootstrap\LoadEnvironmentVariables::class );
|
可以參考分析 bootstrap 流程提到的如何產生 bootstrapper 實例,以及 Container 的 bind()
如何實作,即可了解為何這個做法是可行的。
而 Http Kernel 就不需要覆寫了。這也是目前的做法。