Environment Variables
Table of contents
- The issue with configuration files
- What are environment variables?
- Introducing env files
- PHP and env vars
- WP Starter and env vars
- Environment variables and WordPress
- WP Starter-specific env vars
- Cached Environment
The issue with configuration files
Pretty much all applications need configuration. There are different approaches to that. One of the most used is to have configuration files in some data-exchange format (XML, JSON, Yaml, Neon, Toml…).
PHP applications might use PHP files for configuration.
WordPress uses a single PHP file, wp-config.php
that is used to declare PHP constants with configuration values.
This approach surely has some advantages (speed above all), but also issues. The main problems are two:
wp-config.php
will very likely contain “secrets” that should not be kept under version control, but being the file required by WordPress it is hard to conciliate the two things.wp-config.php
does not support multiple environments. Meaning if the same code will be deployed to, for example, to both a “staging” and a “production” server it will be necessary to have two versions of the file. This is possible using separate VCS “branches” (if the VCS of choice supports them), but then we fall into the previous issue of being forced to keep secrets under version control.
This issue is surely not limited to WordPress.
A modern approach to this issue (see The Twelve-Factor App) is to use environment variables to save configuration values.
What are environment variables?
Environment variables (or simply “env vars”) are key-value pairs that can be set in the environment, i.e. in the server that runs the application.
For example, those could be set into the webserver (Apache, nginx) making the configuration very specific to the server that runs the application.
As additional advantage, env vars can be set “on the fly” acting on the system, e.g. a continuous integration service can set them without touching the code.
Finally, not being code, env vars don’t need to be kept under version control, avoiding the issue of having to keep “secrets” in VCS.
It is undeniable that the setting of values on the “bare environment” during development could be quite cumbersome. This is why many applications and tools support “env files”.
In the rest of the documentation we will refer to “actual environment” to mean variables set on the server itself, to distinguish from variables set by parsing env files.
Introducing env files
An env file is nothing else than a shell script file that does not contain any command, but only variables.
HELLO="Hello"
GREETING="${HELLO} World!"
Tools that support such files read them and set values on the environment “on the fly”.
By convention those files are often named .env
.
PHP and env vars
In PHP there are two functions: getevn
and putenv
that allow to, respectively, read and write env vars on the server in an OS-agnostic way.
There’s nothing in PHP core that parse env files, but is no surprise that there are different libraries to do that.
WP Starter uses one of these libraries: the Symfony Dotenv Component.
WP Starter and env vars
WP Starter uses Symfony Dotenv Component to load an .env
file found in the project root folder of the project (the folder and the file name can be configured, if necessary).
The env vars loaded from the file will never overwrite variables that are set in the actual environment.
Moreover, if the “actual environment” contains all the variables WP Starter and WordPress need, there’s no need to load and parse env files, which is the suggested way to go in production.
Configuring WP Starter to bypass the loading of env files is accomplished via the WPSTARTER_ENV_LOADED
env variable, which when set tells WP Starter to assume all variables are in the actual environment.
Important security note about .env
file
WP Starter loads an .env
file found in the project root folder, and it is worth noting that if no additional configuration is made, project root is also the folder assumed as webroot for the project.
This is a non-issue in local-only installations, however it can be quite a serious issue on anything that goes on-line. In fact, an .env
file inside webroot could expose secrets stored in it (at very minimum DB credentials).
To avoid this issue there are at least three different ways:
- Create a subfolder inside project root and use it as webroot, keeping
.env
file one level above, in the project root. This is the approach that will be shown in the “A Commented Samplecomposer.json
“ chapter. - Configure WP Starter to load
.env
file from a folder that is not publicly accessible, like the parent folder of the project root (if project root is also webroot). This can be done via theenv-dir
setting. Learn more in the “WP Starter Configuration” chapter. - Don’t use env file in production at all, but store env vars in the actual environment. See documentation on how to do it in Apache, and nginx. Note that Docker supports an
.env
file as well (see documentation). By setting env vars that way sensitive application configurations would not be publicly accessible.
Environment variables and WordPress
Although WP Starter loads env vars (no matter if from file or from actual environment), WordPress still needs PHP constants to be set with configuration to work properly.
WP Starter generates a wp-config.php
file that reads env variables and declares PHP constants “on the fly” when an env var matching a WP configuration constant is found.
For example, by having an env file like the following:
DB_NAME=mydb
DB_USER=mydb_user
DB_PASSWORD=mysecret!
WP Starter will load it, will set related environment variables and will also define DB_NAME
, DB_USER
, and DB_PASSWORD
PHP constants so that WordPress can work properly.
If the same env vars would be set in the actual environment instead of in env file, nothing would change.
Note that only variables matching WordPress core constants names will be defined as constants.
If there’s a plugin that supports a constant like "AWESOME_PLUGIN_CONFIG"
, by setting the related env var WP Starter will not declare the constant automatically.
So you might need to write code like:
$config = getenv('AWESOME_PLUGIN_CONFIG');
if ($config) {
define('AWESOME_PLUGIN_CONFIG', $config);
}
There are many places in which such code can be placed, for example a MU plugin.
Alternatively WP Starter can be instructed to do something like this automatically.
Let WP Starter define constants for custom env vars
WP Starter supports an environment variable called WP_STARTER_ENV_TO_CONST
containing a list of of comma-separated environment variables to be turned into constants:
WP_STARTER_ENV_TO_CONST="AWESOME_PLUGIN_CONFIG,ANOTHER_VAR,YET_ANOTHER"
With such env variable set, WP Start will declare constants for the three env variables.
Please note that env variables are always strings, while PHP constants can be any static type. For WordPress constants that is not an issue because WP Starter knows the expected type can cast the value before define the constant. For custom variables a different type can be specified using the NAME:TYPE
syntax . For example:
# This tells WP Starter to create a bool constant for AWESOME_PLUGIN_CONFIG variable
WP_STARTER_ENV_TO_CONST="AWESOME_PLUGIN_CONFIG:BOOL,ANOTHER_VAR"
# This sets the variable that WP Starer will alos turn in a constant
AWESOME_PLUGIN_CONFIG=true
Having an env file like the above, WP Starter will define AWESOME_PLUGIN_CONFIG
constant as a boolean, like so:
define('AWESOME_PLUGIN_CONFIG', true):
WP Starter-specific env vars
As described above, all WordPress configuration constants are natively supported by WP Starter.
Moreover, there are a few env variables that have a special meaning for WP Starter.
DB check env vars
During its bootstrap process, before doing any operation on the system, WP Starter checks if the environment is already setup for database connection. If so, WP Starter attempts a connection and launches a very simple SQL command. Thanks to that it can determine if connection is possible, if the WP DB exists, and if WP is installed.
This information is stored in three env vars whose names are stored in WeCodeMore\WpStarter\Util\DbChecker
class constants:
DbChecker::WPDB_ENV_VALID
- is non-empty if connection to DB is possibleDbChecker::WPDB_EXISTS
- is non-empty if DB exists and is usableDbChecker::WP_INSTALLED
- is non-empty if WordPress is installed
The three env vars are registered in the order they are listed above: if one is non-empty the previous must be non-empty as well.
Sometime it might be desirable to bypass this WP Starter check and there’s a way to accomplish that via the skip-db-check
setting. Learn more about that in the “WP-Starter-Configuration” chapter.
WordPress Configuration
Those are a few env vars that are used in wp-config.php
that WP Starter generates. They are documented in the “WordPress Integration” chapter.
Cached Environment
To parse env files and setup environment variables, and then setup WordPress constants based on the environment, is a bit expensive.
Half of the reason is the env file parsing itself (which can be avoided by setting environment variables in the actual environment). The other half is the fact that WP Starter has no way to know which environment variables matching WP constants are set in the environment before trying to access them. Which means that WP Starter needs to loop all the possible WordPress constants, and for each of them try to access an environment variable named in the same way and define a constant for any found.
To avoid this overhead at every request, the WP Starter’s wp-config.php
registers a function to be run on “shutdown” that dumps the environment variables that have been accessed with success during the first request into a PHP file so that on subsequent requests the environment “bootstrap” will be much faster.
This cache file is saved in the same folder that contains the .env
file and is named .env.cached.php
.
However, having a cached environment means that any change to it will require the cache file to be deleted. WP Starter does it via one of its steps (“flush-env-cache”), so after every Composer install/update, or after running WP Starter command, the environment cache is always clean.
It is also possible to clean environment cache on demand by running the command:
composer wpstarter flush-env-cache
(Read more about running specific steps via wpstarter
command in the “Command-line interface” chapter)
There are several ways to prevent WP Starter to generate and use cached environment in first place.
- when
WP_ENVIRONMENT_TYPE
env var is"local"
the cache by default is not created. - when the
cache-env
configuration isfalse
, the cache by default is not created. - there’s a WordPress filter
'wpstarter.skip-cache-env'
that can be used to disable the cache creation.
The 'wpstarter.skip.cache-env'
filter is interesting because it allows disabling cache in specific environments, thank to environment-specific PHP files. For example, it is possible to skip environment cache in “development” environment having a development.php
file that contains:
add_filter('wpstarter.skip-cache-env', '__return_true');
The filter is executed very late (so could be added in MU plugins, plugins and even themes) and also passes the environment name as second parameter.
For example, to only allow cache in production a code like the following can be used:
add_filter('wpstarter.skip-cache-env', function ($skip, $envName) {
return $skip || $envName !== 'production';
});
Next: WordPress Integration