Simplifying environment detection in Laravel

  • Reading time: 2 min
  • Published 5 years ago

Laravels environment detection is a pretty rock solid way of choosing a different configuration based on the current application environment. Currently, Laravel does this by looking up the machine's hostname and checking into which environment it was sorted. The hash map for that is contained in bootstrap/start.php. Unfortunately, solely relying on the hostname can be a tedious job on two ends of the web app development spectrum.

On the one hand, if multiple people work on an app and want to use their local computer as a testing ground, all of their hostnames (or maybe some clever wildcards) may have to be added to the local environment.

On the other hand, when upscaling an app horizontally, a multitude of hosts running the code might be around. Adding all of their hostnames might cause an even bigger hassle since they might not even all be known at deploy time.

I've come up with "One ring to rule them all" kind of solution that reduces my environment selection array to the following:

$env = $app->detectEnvironment([
  // set LARAVEL_ENV = production on production systems
  $_SERVER['LARAVEL_ENV'] => [gethostname()]
]);

Now, all you have to do is export the LARAVEL_ENV variable to the user your app is executed with, which for local testing purposes can be as quick and easy as typing export LARAVEL_ENV='local' in your favorite shell.

Update

After some testing in the wild, I discovered a serious flaw with my above approach: It will fail horribly if the environment variable is not set. To fix this I went ahead and dropped in a basic catch-almost-all for local environments. If that one does not evaluate, Laravel will automagically choose the production environment.

if (isset($_SERVER['LARAVEL_ENV']))
{
  $env = $app->detectEnvironment([
    $_SERVER['LARAVEL_ENV'] => [gethostname()]
  ]);
} else
{
  $env = $app->detectEnvironment(['local' => ['*.local', 'local.*', 'localhost']]);
}