I'm using Laravel 5.1.44, and even though I have both a .env.testing
file setup with different values, as well as App::environment()
returning 'testing'
, Laravel still seems to only be using values from the main .env
file.
Is there something else I should be double-checking to make sure I didn't screw up or forget to set something?
The ability to use environment specific .env
files (e.g. .env.testing
) was not available until Laravel 5.2.13. Even then, it only works if you are not using config caching.
The easiest option is to just add all your testing specific environment variables to your phpunit.xml
file. As you've mentioned, you've already got a few in there, it should be no issue to add any additional ones you need.
If you really want the environment specific .env
file functionality in Laravel 5.1, you can try the following. Note, this is untested, and just an assumption of what should work based off of looking at the source code.
The .env
file is loaded in a bootstrap class called DetectEnvironment
. The idea is you create your own bootstrap class that modifies the filename of the .env
file that DetectEnvironment
will load, and then you update your Kernel
files so that your new bootstrap class is called, and called before the
DetectEnvironment
bootstrapper.
So, first, create a new bootstrapper class (e.g. app\Bootstrap\CustomEnvironment.php
):
<?php
namespace App\Bootstrap;
use Illuminate\Contracts\Foundation\Application;
class CustomEnvironment
{
/**
* Bootstrap the given application.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function bootstrap(Application $app)
{
// APP_ENV must already be set.
// We must know which environment file to look for.
if (! env('APP_ENV')) {
return;
}
// Build the file name to look for (e.g. .env.testing)
$file = $app->environmentFile().'.'.env('APP_ENV');
// If the file exists, set the App to load from that file.
// The actual loading will take place in DetectEnvironment
if (file_exists($app->environmentPath().'/'.$file)) {
$app->loadEnvironmentFrom($file);
}
}
}
Now that you have a bootstrap class to update the .env
file to be loaded, you need to add it to your Kernel
|s to make sure it is called before the DetectEnvironment
bootstrap class.
Add the following property to your app/Console/Kernel.php
file:
/**
* The bootstrap classes for the application.
*
* @var array
*/
protected $bootstrappers = [
'App\Bootstrap\CustomEnvironment',
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
'Illuminate\Foundation\Bootstrap\ConfigureLogging',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
'Illuminate\Foundation\Bootstrap\RegisterFacades',
'Illuminate\Foundation\Bootstrap\SetRequestForConsole',
'Illuminate\Foundation\Bootstrap\RegisterProviders',
'Illuminate\Foundation\Bootstrap\BootProviders',
];
Add the following property to your app/Http/Kernel.php
file:
/**
* The bootstrap classes for the application.
*
* @var array
*/
protected $bootstrappers = [
'App\Bootstrap\CustomEnvironment',
'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',
];
Note, they may look similar at first glance, but the bootstrappers are different between the Console
and Http
kernels (Console
has one more bootstrapper). Don't just copy one of the above and add it to both files.
Another simpler way would be to setup a before listener for the DetectEnvironment
bootstrapper, and set the file to load in an event closure.
So, for example, in your bootstrap\app.php
file, add the following code before the return $app;
statement:
$app->beforeBootstrapping(
'Illuminate\Foundation\Bootstrap\DetectEnvironment',
function($app) {
// APP_ENV must already be set.
// We must know which environment file to look for.
if (! env('APP_ENV')) {
return;
}
// Build the file name to look for (e.g. .env.testing)
$file = $app->environmentFile().'.'.env('APP_ENV');
// If the file exists, set the App to load from that file.
// The actual loading will take place in DetectEnvironment
if (file_exists($app->environmentPath().'/'.$file)) {
$app->loadEnvironmentFrom($file);
}
}
);
Using the beforeBootstrapping()
method, the Closure in the second parameter will be executed immediately before the bootstrapper in the first parameter is called. Now you don't have to worry about Kernels or extra classes or anything.