Laravel 5.0 - Environment Detection & Environment Variables

(This is part of a series of posts on New Features in Laravel 5.0.)

  1. Laravel 5.0 - Form Requests
  2. Laravel 5.0 - ValidatesWhenResolved
  3. Laravel 5.0 - Directory structure and namespace
  4. Laravel 5.0 - Route Caching
  5. Laravel 5.0 - Cloud File Drivers
  6. Laravel 5.0 - Method Injection
  7. Laravel 5.0 - Route Annotations (removed)
  8. Laravel 5.0 - Event Annotations (removed)
  9. Laravel 5.0 - Middleware (Filter-style)
  10. Laravel 5.0 - Environment Detection & Environment Variables
  11. Laravel 5.0 - Event Scheduling
  12. Laravel 5.0 - Commands & Handlers
  13. Upgrading from Laravel 4 to Laravel 5
  14. Bringing Whoops Back to Laravel 5
  15. Laravel 5.0 - Events & Handlers
  16. Laravel 5.0 - Generating Missing Events
  17. Laravel 5.0 - Custom Error Pages
  18. Laravel 5.0 - Eloquent Attribute Casting

If you've followed my blog for a while, you've probably seen me struggle with Laravel's environment detection--especially regarding using environment variables. (Example)

Thankfully, Laravel 5.0 vastly simplifies environment detection. In 4, you could have multiple environment files based on the environment name (.env.php, .env.local.php, etc.). In all honesty, I never used the environment-specific aspect; I imagine you could theoretically use it to commit all of your environment files to your repo. But since we don't commit any of our environment files, it was a useless distinction--and it forced the delayed loading of the environment file, because it couldn't be loaded until after the environment was detected.

Introducing PHP dotenv #

Well, NO MORE. Laravel 5.0 is using PHP dotenv, a proven 3rd-party library that loads from a single .env file.

Every Laravel app now ships with a default .env.example file, which at the moment looks like this:

APP_ENV=local
APP_KEY=SomeRandomString
DB_USERNAME=homestead
DB_PASSWORD=homestead

In order to use this file, just copy it and name the copy .env. Why aren't we renaming the original? You'll see in a second.

Now, you can edit your APP_ENV--which, as you can tell from the default, is the primary way for us to set the application environment name. Check out the newer, simpler environment detection in bootstrap/environment.php:

$env = $app->detectEnvironment(function()
{
    return getenv('APP_ENV') ?: 'production';
});

That's a beautiful thing!

Customizing the example file #

So, why are we copying the .env.example instead of just renaming it? Well, imagine your app for a second. Imagine it has a consistent need for 10 environment variables to be defined. Sure, you'll have reasonable fallbacks if they're not defined, but it's still a better deal if you have them all.

Where are you going to store the directions for which variables each app's .env file should set? You could store it in the readme, sure... or you could just update the .env.example file to be the directions for which variables each install of your app should have.

That's it! Need 10 variables for each install? Add those 10 variables to your .env.example file with sensible (or silly) defaults. This file will get committed to your source control, and then each new install can start out by running cp .env.example .env and then customizing .env.

Referencing previous variables #

You can learn more from the PHP dotenv docs, but here's a clever note: You can reference environment variables in later environment variables. Check out this example from their readme:

BASE_DIR=/var/webroot/project-root
CACHE_DIR=$BASE_DIR/cache
LOG_DIR=$BASE_DIR/logs

That's clever.

Requiring variables #

What if you want to ensure all the required variables are set up front, rather than waiting for the app to break when it accesses them?

Dotenv::required('DB_USERNAME');
// or
Dotenv::required(['DB_HOST', 'DB_NAME', 'DB_USERNAME', 'DB_PASSWORD']);

Done. If it's not defined, it'll throw a RuntimeException.

Conchl #

Simple, easy, powerful. And this will completely invalidate all of my blog posts, workarounds, and complaints about environment detection in Laravel. Now it's simple to define your environment name and your environment variables in a single, consistent, predictable manner.


Comments? I'm @stauffermatt on Twitter


Tags: laravel | 5.0 | laravel 5

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt


Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.