Set Environment Variables in PHP with PHP dotenv

Set Environment Variables in PHP with PHP dotenv

There are a number of ways to set environment variables in PHP. But the approach I use most often in development is a wonderful package called PHP dotenv. In this tutorial, I’m going to step you through how to install and use it.


Before we dive right on in, why would you set and use environment variables anyway? Why wouldn’t you just store credentials in your code, where you can see and quickly edit them?

Honestly? Because you should never store credentials or any form of sensitive data in your code. Ever! Among others, here are two key reasons.

It makes it easier for malicious actors to access

Firstly, if anyone ever gets access to your source code, whether that be a malicious actor or a disgruntled former co-worker, etc, they have access to secret keys, API keys, usernames, passwords – everything. Given that, they can make authenticated requests and no one would be any the wiser.

I’m not trying to say that people are out to get you, or that you should be paranoid. However, there are people who, for a wide number of reasons, look for the opportunity to do malicious things. By storing secure credentials and sensitive data in your code, you’re making it pretty easy for them to do so. All it would take is an accidental server misconfiguration or a security breach and the secure data is available for all the world to see.

What’s more, if you put these credentials in your code, and you’re using version control, then they’re also stored there too. Yes, you can purge information from Git repositories that never should have been there, but it’s best to never put that kind of secure data under version control in the first place.

It makes it harder to deploy the code

Secondly, if secure credentials are stored directly in your code, then every deployment must use them. Think about:

  • How challenging doing so would make deploying the application to different environments, such as one for testing, QA, and staging
  • How hard it would be for new developers on a project to get up and running, even if they’re using tooling such as Docker Compose
  • The risk that new developers run of clobbering the data of other developers – or of production!
  • How hard it will be to maintain that code

By having code set in environment variables, the credentials are kept out of the code. And by having secure credentials and other details retrieved from environment variables:

  • Developers don’t need to pull the latest copy of a codebase to update variables
  • Developers don’t need to grep a codebase to find variables so that they can update them
  • Secure credentials can never accidentally be stored under version control
  • There’s a clear record of what variables need to be set for an application to work
  • Each developer can use their own values
  • It’s simpler to deploy applications to multiple environments
  • Environment variables can be set, regardless of environment, using a range of high-quality tools such as HashiCorp Vault, GitHub Encrypted Secrets, or AWS Secrets Manager.

What other benefits can you think of? Let me know in the comments, or tweet me. Otherwise, let’s get in and write some code so you can see what I mean.

Prerequisites

To following along with this tutorial, you’re going to need the following:

How does PHP dotenv work?

PHP dotenv is, conceptually, quite simple. By default, it loads environment variables from a file named .env making them available to the getenv() method, and loads them in to $_ENV and $_SERVER. It does more than that, as you’ll see shortly, but for now that’s the essence of what it does.

How will the code work?

For the purposes of this tutorial, let’s say that your code needs an API key to make authenticated requests, such as to SendGrid or Twilio. The code will retrieve it from PHP’s $_SERVER superglobal using the key API_KEY, after PHP dotenv loads it there.

Install PHP dotenv

Thanks to Composer, there’s virtually nothing you need to install PHP dotenv, other than running the following command.

composer require vlucas/phpdotenv

Create a dotenv file

In the top-level directory of your project, create a new file named .env. In it add the configuration below.

API_KEY=1234567890

It’s a very strong API key, no? But seriously, set it to whatever you want. It’s not important for the purposes of this tutorial.

Use PHP dotenv to load the environment variables

Next, have PHP dotenv load API_KEY read .env and load the environment variables – as early in the lifecycle of your application as possible. To do that, add the following code to the top of your application’s main file, likely public/index.php, right after it includes Composer’s autoloader, as in the example below.

require __DIR__ . '/vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/');
$dotenv->load();

...

This way, your application’s code will always have access to the API key.

Use the environment variables in your application’s code

Now, all you need to do is to reference either $_ENV['API_KEY'] or $_SERVER['API_KEY'] in your application, when you need to reference the API key.

One way that I’ve become fond of when working with Mezzio, is to set the relevant configuration variables, which are stored in the DI (Dependency Injection) Container, from $_SERVER, and then use those configuration variables, as in the following example.

<?php

return [
    'service' => [
        'api_key' => $_SERVER['API_KEY']
    ]
];

I find it simpler and it’s analagous to what other frameworks, such as Laravel and Symfony do.

Use a different dotenv file

By default, PHP dotenv will look for a dotenv file named .env in the directory passed to createImmutable(). However, you may prefer to name the file differently, for whatever reason. To use a different name or supply a range of potential file names, supply them as the second parameter to createImmutable(), as in the example below.


// Use a different file name
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/', '.dotenv');

// Supply a range of file names to use
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/', ['.dotenv', '.dot_env']);

Ensure that environment variables are defined

Another helpful thing you can do is require one or more environment variables to be set. I find this to be a good way to provide a documented list of all the environment variables which an application needs. To do this, use the required() method, as in the following example.

require __DIR__ . '/vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/');
$dotenv->load();
$dotenv->required([
    'API_KEY',
]);

...

Now, if API_KEY is not set in the dotenv file, PHP dotenv will throw an exception. You can take this further by also requiring the variable to not be empty, as in the example below.

require __DIR__ . '/vendor/autoload.php';

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/');
$dotenv->load();
$dotenv->required([
    'API_KEY',
])->notEmpty();

...

That’s how to set environment variables in PHP with PHP dotenv

I hope that this short tutorial’s shown you both why it’s a good idea to keep secure credentials out of code, and how to do it, using PHP dotenv. If you’d like to learn several other ways of working with environment variables in PHP, check out this tutorial that I wrote.

Otherwise, have a play with PHP dotenv and the other functionality it has to offer. If you already use it, what’s your experience been with it?


You might also be interested in...


Want more tutorials like this?

If so, enter your email address in the field below and click subscribe.

You can unsubscribe at any time by clicking the link in the footer of the emails you'll receive. Here's my privacy policy, if you'd like to know more. I use Mailchimp to send emails. You can learn more about their privacy practices here.


Join the discussion

comments powered by Disqus