Working with Environment Variables in PHP

October 14, 2021
Written by

Environment variables are an excellent way to configure PHP applications because they keep the application’s settings outside of the code. By doing this, it's easier to prevent secure credentials from being exposed, maintain applications, and use applications across multiple environments.

In this tutorial, you're going to learn about some of the many ways in which environment variables can be set and retrieved in PHP applications. That way, your application can access all the information that it needs, such as API keys, uploaded files, query strings, and form data.

How to access environment variables in PHP

Use PHP's Superglobals

One of the most common ways that environment variables are accessed in PHP is through the use of Superglobals. These are built-in, predefined variables, available in all scopes. Initialised by the PHP runtime, they organise PHP's environment information in a (mostly) logical and efficient way, so that you only need to consult one array to retrieve the information you need.

For example, $_SERVER contains request headers, paths, and script locations, $_SESSION contains session variables, and $_POST contains variables passed to the current script when called with the HTTP POST method.

That said, there are some things to be aware of.

  • Firstly, depending on how the variables_order directive is set, one or more of the Superglobal arrays may be empty. This is important to check, if your application depends on a given Superglobal being populated.
  • Secondly, the variables contained in $_SERVER and $_ENV (which contains variables imported from the environment under which the PHP parser is running) can overlap with one another, depending on the script's context. This might be confusing if you were expecting the keys to be unique across all the Superglobals.

Differences between SAPI/CGI, and CLI environments

In addition to the variables_order directive, the environment also plays a part in what information is set in the Superglobals. Specifically, if your application is running using CGI, FastCGI, or SAPI, then $_SERVER, in addition to the normal variables, will be populated with environment variables. Alternatively, if you're using the PHP CLI, then only $_SERVER will be set.

Using getenv()

In addition to using PHP's Superglobals, you can also use getenv() to retrieve an environment variable. If the function is called without an argument, then it returns all available environment variables. If an argument is passed, however, the value of an environment variable with that name is returned.

You can see examples of its usage below.

echo getenv('SHELL');
foreach (getenv() as $key => $value) {
    echo $key . ' - ' . $value;
}

As with PHP's Superglobals, there is a catch to using this function. Quoting the function's documentation:

If PHP is running in a SAPI such as Fast CGI, this function will always return the value of an environment variable set by the SAPI, even if putenv() has been used to set a local environment variable of the same name. Use the local_only parameter to return the value of locally-set environment variables.

Please be aware that getenv() is not thread safe.

Using apache_getenv()

If you're using Apache as your web server, then you have one extra function that you can use: apache_getenv(). This function retrieves an environment variable set in the Apache process. You can see an example of using it below.

echo apache_getenv('NAME');

Don't implicitly trust environment variables!

It's important to stress that — regardless of where data comes from, whether it comes from one of PHP's Superglobals, a web server configuration, or an operating environment — do not implicitly trust it! Environment variables should be filtered and validated just like any other data that is external to your application.

How to set environment variables

As well as reading environment variables, it's also helpful to know how to set them, that way, you know how to change them, as and when necessary. In the following examples, we're going to set an environment variable, NAME, to "Robert Smith", lead singer of English rock band The Cure.

Setting them in the environment

Before you start your web server or execute your PHP script, you can set environment variables in the current environment.

If you'd like to learn about setting environment variables in greater depth, Dominik Kundel has written a detailed blog post about it.

UNIX, Linux, and macOS

If you're using one of these three operating systems or a variant such as BSD, then there are three scopes for which you can set an environment variable:

  • Available to the current environment (session) and all child sessions.
  • Available only to the current session.
  • Available only to a specific process.

You can see examples of all three in the code below.

# Available to the current environment (session) and all child sessions.
export NAME="Robert Smith"

# Available only to the current session.
NAME="Robert Smith"

# Available only to a specific process.
NAME="Robert Smith" php script.php

Microsoft Windows

Setting environment variables is a little different in Microsoft Windows. You can either set them viathe Control Panel, or you can set them in the command prompt or PowerShell console. There are examples of the latter two below.

# Set NAME in the Windows Command Prompt
set NAME="Robert Smith"

# Set NAME in the Windows PowerShell console
$Env:NAME = "Robert Smith"

Using Docker

If you're using Docker, you can set environment variables in Dockerfiles using the ENV command, as in the example below.

ENV NAME "Robert Smith"

If you're building a multi-container configuration using Docker Compose, you can set environment variables in docker-compose.yml using the environment key, as in the example below.

environment:
  - NAME="Robert Smith"

There are a number of other ways to set environment variables when working with Docker, which you can read about in the Docker documentation and the Docker Compose documentation.

Using putenv()

Using this function, you can set the value of an environment variable — and unset it —  within the current request. In the next request, the variable, if set outside of the current request, will return to its original value.

Variables set in this way are also available to processes invoked by that script, and are only available by calling getenv().

You can see an example of both functions in the code below.

// Set the environment variable, NAME.
putenv('NAME="Robert Smith"');

// Retrieve the environment variable, NAME.
echo getenv('NAME');

// Unset the environment variable, NAME.
putenv('NAME');

Please be aware that putenv() is not thread safe.

Using apache_setenv() Similar to putenv(), is apache_setenv(). This function sets an Apache process-specific environment variable. Naturally, this function and its complement are only available when using Apache. You can see an example of using it below.

apache_setenv('NAME', 'Robert Smith');
echo apache_getenv('NAME');

Setting environment variables in an NGINX configuration

If you're using NGINX as your web server, you can use the fastcgi_param directive to set an environment variable. The directive takes a case-sensitive name and value, which must be quoted if it contains spaces.

fastcgi_param NAME "Robert Smith";

These variables are available via getenv(), and in the $_ENV and $_SERVER Superglobal arrays.

Setting environment variables in an Apache configuration

If you're using Apache as your web server, then you can use the SetEnv directive to set environment variables. The directive can be used in Apache's main server configuration, a virtual host configuration, a directory configuration, or an .htaccess file.

The directive takes a case-sensitive name and value, which must be quoted if it contains spaces. If no value is provided, the variable will be initialised to an empty string.

SetEnv NAME "Robert Smith"

Unlike using fastcgi_param in NGINX, environment variables set using SetEnv in Apache (or one of the related functions) are only available in the $_SERVER Superglobal.

Using .env files

While each of the above ways have their advantages, there are a couple of disadvantages to bear in mind:

  • They can be challenging to maintain over the course of time, based on a project's complexity.
  • There is no central list of the required environment variables, details about what a given variable does, nor of their allowed data types.

An alternative approach, one that's gained significant traction in PHP over recent years, is using dotenv files, named after the de facto file name: .env. These are plain text files that define the environment variables required for an application to work as a list of key/value pairs.

You can see an example below.

NAME="Robert Smith"

Assuming that the example above was the .env file for our project, we could use a package such as vlucas/phpdotenv, which reads .env files, by default and adds the variables defined in them to the $_ENV and $_SERVER Superglobals.

To do that, we'd first install the package as an application dependency by running the command below.

composer require vlucas/phpdotenv

Then, we'd use the package to load environment variables, as in the example below.

<?php

declare(strict_types=1);

require_once('vendor/autoload.php');

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

echo $_ENV['NAME'] . "\n";
echo $_SERVER['NAME'] . "\n";
  • Use safeLoad() instead of load() to avoid throwing an exception if .env is not found.
  • Pass a file path as the second parameter to createImmutable() to use a file other than .env.

A note about .env file security

It's important to be aware that .env files must not be stored under version control! 

If that happens, all of the security benefits of using dotenv files are lost because any sensitive data contained in them is then available to anyone who can access the repository. That's why it's common to exclude them from version control, such as by adding .env (and variations of the filename) to a project's .gitignore file when using Git.

That's how to work with environment variables in PHP

I hope this article helped you understand how to use environment variables in your PHP projects. Do you have any other ways to work with environment variables? I’d love to know!

Matthew Setter is a PHP Editor in the Twilio Voices team and a polyglot developer. He’s also the author of Mezzio Essentials and Docker Essentials. When he’s not writing PHP code, he’s editing great PHP articles here at Twilio. You can find him at msetter@twilio.com; he's also settermjd on Twitter and GitHub.