Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5 load env file based on .env.master?

Tags:

php

laravel

I'm planing to do something like, specifying what env file to load during application bootstrap time by creating a variable in .env.master such as ENV_VER = dev.env

This is because I have several branches such as development, release-1.1 and etc. Thus by loading the env file based on the name specified in a master env file, developers no longer have to copy and paste new variables into their local copy of .env and instead, just specify what version of env file to load in the master env file. By the way, I have several env files such as dev.env, 1.6.env etc.

Is it possible?

like image 243
AlexZai Avatar asked May 02 '17 06:05

AlexZai


2 Answers

Definitely, me myself I tend to "bend" a framework little bit everytime and there's always a way, not always the best solution though. I'm not giving a whole implementation here, just pointing you in some direction, that might work for you.

You can extend Laravel's base application class Illuminate\Foundation\Application, which contains $environmentFile variable storing environment file loaded during appplication bootstrap or possibly override function loadEnvironmentFrom($file) or environmentFile(). The whole logic is up to you.

So basically all you need to do in order to be able to "play" with .env loading is...

Create a new application class extending Laravel's one:

namespace MyNamespace;
...

use Illuminate\Foundation\Application as App;

/**
 * I'm doing alots of magic with .env in this class
 */
class Application extends App
{
    ... 

    /**
     * The environment file to load during bootstrapping.
     *
     * @var string
     */
    protected $environmentFile = '.env.main';

    ...
}

And now, because we have a new bootstraping class, we have to tell Laravel we want to use it. So you'll have to modify bootstrap/app.php file in point where a new instance is being created:

...
$app = new MyNamespace\Application(
    realpath(__DIR__.'/../')
);
...

Note: For inspiration I recommend you to really look at Illuminate\Foundation\Application class.

like image 102
hradecek Avatar answered Oct 17 '22 13:10

hradecek


In laravel 5.5+ you can, maybe earlier, you can set your server have a APP_ENV environment or server variable that the process can see (apache, command line...)

this will allow you to use a suffix or file extension on your .env files for auto loading those files...

  • APP_ENV=dev :: .env.dev
  • APP_ENV=production :: .env.production

much easier than other solutions.

If you want to look into how this is done, it starts with

1. application bootstrappers

protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\SetRequestForConsole::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];

2. LoadEnvironmentVariables

first the environment is determined…

\Illuminate\Foundation\Bootstrap\LoadConfiguration::bootstrap calls \Illuminate\Foundation\Application::detectEnvironment

If

--env={env} for CLI then it will use that for APP_ENV.

Else

\Illuminate\Foundation\EnvironmentDetector::detectWebEnvironment is called which uses a callback…

function () use ($config) {
            return $config->get('app.env', 'production');
        }

where app.env defaults to env('APP_ENV', 'production')

3 LoadConfiguration

\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::bootstrap calls... \Illuminate\Foundation\Application::afterLoadingEnvironment which eventually gets to

\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::checkForSpecificEnvironmentFile

which sets the environment file based on app env IF the file exists.

        $this->setEnvironmentFilePath(
            $app, $app->environmentFile().'.'.env('APP_ENV')
        );

allowing it to load the .env.{APP_ENV} instead of .env

NOTE: Testing.

when running php unit tests. the Illuminate/Foundation will try to load the .env.testing file for configurations!

like image 36
Artistan Avatar answered Oct 17 '22 12:10

Artistan