I admit it, this doesn’t improve your stores performance at all. But the benefits of using a .env file are that you keep important credentials for  databases, payment gateways, etc. out of your document root, out of your database and thus have a more secure setup, with a single configuration file. An .env file should never be committed to GitHub so it should not be part of your code repository. You will need to add /.env to your .gitignore file. For different environments (development, staging, production) the .env file would look different. Also you will benefit because this helps you to keep these different environments more in sync.

Step 1: Let’s create the .env file

.env#--------------------------------------------------------------------------------------------------##                                       ENVIRONMENT SETTING                                        ## It can be anything, but "development", "staging" and "production" are supported out of the box.  ## Do not use "development" on production and viceversa, because it has effect on debug settings.   ##--------------------------------------------------------------------------------------------------#WORDPRESS_ENV=development#--------------------------------------------------------------------------------------------------##                                   MANDATORY DATABASE SETTINGS                                    ##--------------------------------------------------------------------------------------------------#DB_NAME="my-project"DB_USER="my-project"DB_PASSWORD="my-password"#--------------------------------------------------------------------------------------------------##                                          HOME PAGE URL                                           ## Optional, but If not set current server name will be used, e.g. http://www.example.com           ##--------------------------------------------------------------------------------------------------#WP_HOME="http://localhost:8080"#####################################################################################################                                                                                                  ## Most of the times you do NOT need to edit further.                                               ## Below there's a cheat sheet of all the available settings, all are optional, feel free to delete ## unused settings when you are done with editing.                                                  ## Note that settings are commented (prefixed with #). Remove comment to be able to use a setting.  ## Edit with care. Do nothing if in doubt. Double check before save.                                ## For help see http://codex.wordpress.org/Editing_wp-config.php                                    ##                                                                                                  ## Table of Contents:                                                                               ##  - OTHER DATABASE SETTINGS                                                                       ##  - MULTISITE                                                                                     ##  - CACHE                                                                                         ##  - DEBUG                                                                                         ##  - OTHER PATHS & URLS                                                                            ##  - WP AUTO-UPDATES                                                                               ##  - POST & MEDIA SETTINGS                                                                         ##  - PERFORMANCE                                                                                   ##  - COOKIE                                                                                        ##  - SECURITY                                                                                      ##  - FILESYSTEM                                                                                    ##  - CRON                                                                                          ##  - LANGUAGES                                                                                     ##  - PROXY                                                                                         ##  - MISCELLANEOUS                                                                                 ##                                                                                                  ######################################################################################################--------------------------------------------------------------------------------------------------##                                      OTHER DATABASE SETTINGS                                     ##--------------------------------------------------------------------------------------------------##DB_HOST#DB_CHARSET#DB_COLLATE#DB_TABLE_PREFIX#DO_NOT_UPGRADE_GLOBAL_TABLES#WP_ALLOW_REPAIR#CUSTOM_USER_TABLE#CUSTOM_USER_META_TABLE#--------------------------------------------------------------------------------------------------##                                            MULTISITE                                             ## As of WP 3.0, you have the ability to create a network of sites by using the multisite feature.  ## See http://codex.wordpress.org/Create_A_Network                                                  ##--------------------------------------------------------------------------------------------------##WP_ALLOW_MULTISITE=false#MULTISITE=false#MU_BASE=/#ALLOW_SUBDIRECTORY_INSTALL=false#SUBDOMAIN_INSTALL=true#DOMAIN_CURRENT_SITE#PATH_CURRENT_SITE=/#SITE_ID_CURRENT_SITE=1#BLOG_ID_CURRENT_SITE=1#NOBLOGREDIRECT={$WP_SITEURL}#UPLOADBLOGSDIR=blogs.dir#UPLOADS=files#BLOGUPLOADDIR=files#WPMU_ACCEL_REDIRECT=false#WPMU_SENDFILE=false#--------------------------------------------------------------------------------------------------##                                              CACHE                                               ##--------------------------------------------------------------------------------------------------##WP_CACHE#--------------------------------------------------------------------------------------------------##                                              DEBUG                                               ## If you set WORDPRESS_ENV, default debug values are used based on that.                           ##--------------------------------------------------------------------------------------------------##WP_DEBUG=true#WP_DEBUG_LOG=false#WP_DEBUG_DISPLAY=true#SAVEQUERIES=true#SCRIPT_DEBUG=true#ERRORLOGFILE=/log/error.log#DIEONDBERROR=true#--------------------------------------------------------------------------------------------------##                                           URLS & PATHS                                           ## If WP_HOME above is set, all other urls are set properly in the great majority of the cases.     ## For very custom installations you may need to set some of the following. Do nothing if in doubt. ##--------------------------------------------------------------------------------------------------##WP_SITEURL#WP_CONTENT_DIR=./../wp-content#WP_CONTENT_URL={$WP_SITEURL}/wp-content#WP_PLUGIN_DIR={$WP_CONTENT_DIR}/plugins#WP_PLUGIN_URL={$WP_CONTENT_URL}/plugins#WPMU_PLUGIN_DIR={$WP_CONTENT_DIR}/mu-plugins#WPMU_PLUGIN_URL={$WP_CONTENT_URL}/mu-plugins#WP_TEMP_DIR=tmp#--------------------------------------------------------------------------------------------------##                                         WP AUTO-UPDATES                                          ##--------------------------------------------------------------------------------------------------##AUTOMATIC_UPDATER_DISABLED=false#WP_AUTO_UPDATE_CORE=false#CORE_UPGRADE_SKIP_NEW_BUNDLED=true#--------------------------------------------------------------------------------------------------##                                      POST & MEDIA SETTINGS                                       ##--------------------------------------------------------------------------------------------------##AUTOSAVE_INTERVAL=60#EMPTY_TRASH_DAYS=30#WP_POST_REVISIONS=true#MEDIA_TRASH=false#IMAGE_EDIT_OVERWRITE=true#--------------------------------------------------------------------------------------------------##                                           PERFORMANCE                                            ##--------------------------------------------------------------------------------------------------##COMPRESS_CSS=false#COMPRESS_SCRIPTS=false#CONCATENATE_SCRIPTS=false#ENFORCE_GZIP=false#--------------------------------------------------------------------------------------------------##                                             COOKIE                                               ##--------------------------------------------------------------------------------------------------##COOKIEHASH#PASS_COOKIE#LOGGED_IN_COOKIE#AUTH_COOKIE#SECURE_AUTH_COOKIE#USER_COOKIE#TEST_COOKIE#COOKIE_DOMAIN#COOKIEPATH#SITECOOKIEPATH#ADMIN_COOKIE_PATH#PLUGINS_COOKIE_PATH#--------------------------------------------------------------------------------------------------##                                             SECURITY                                             ##--------------------------------------------------------------------------------------------------##DISALLOW_FILE_MODS=false#DISALLOW_FILE_EDIT=false#DISALLOW_UNFILTERED_HTML=true#ALLOW_UNFILTERED_UPLOADS=false#FORCE_SSL_LOGIN=false#FORCE_SSL_ADMIN=false#WP_HTTP_BLOCK_EXTERNAL#WP_ACCESSIBLE_HOSTS#--------------------------------------------------------------------------------------------------##                                         FILESYSTEM & FTP                                         ##--------------------------------------------------------------------------------------------------##FS_CHMOD_DIR=0755#FS_CHMOD_FILE=0644#FS_METHOD#FS_TIMEOUT=30#FS_CONNECT_TIMEOUT=30#FTP_USER#FTP_PASS#FTP_HOST#FTP_SSL#FTP_SSH#FTP_BASE#FTP_CONTENT_DIR#FTP_PLUGIN_DIR#FTP_PUBKEY#FTP_PRIKEY#--------------------------------------------------------------------------------------------------##                                               CRON                                               ##--------------------------------------------------------------------------------------------------##ALTERNATE_WP_CRON=false#DISABLE_WP_CRON=false#WP_CRON_LOCK_TIMEOUT=60#--------------------------------------------------------------------------------------------------##                                            LANGUAGES                                             ## WPLANG is deprecated since WP 4, use only for backward compatibility issues                      ##--------------------------------------------------------------------------------------------------##WPLANG=en_EN#WP_LANG_DIR={$WP_CONTENT_DIR}/tmp#--------------------------------------------------------------------------------------------------##                                             MEMORY                                               ##--------------------------------------------------------------------------------------------------##WP_MEMORY_LIMIT=64M#WP_MAX_MEMORY_LIMIT=256M#--------------------------------------------------------------------------------------------------##                                              PROXY                                               ##--------------------------------------------------------------------------------------------------##WP_PROXY_HOST#WP_PROXY_PORT#WP_PROXY_USERNAME#WP_PROXY_PASSWORD#WP_PROXY_BYPASS_HOSTS#WP_ACCESSIBLE_HOSTS#WP_HTTP_BLOCK_EXTERNAL#--------------------------------------------------------------------------------------------------##                                          MISCELLANEOUS                                           ##--------------------------------------------------------------------------------------------------##WP_MAIL_INTERVAL=300#WP_DEFAULT_THEME=twentyfifteen

This file is taken from Jeff Behnke’s perfect example on GitHub. Save it into your project root folder and add it to your .gitginore file /.env in order to prevent it from being committed to your repo. It’s also important that you store it outside your document root folder so that these credentials are not accessible on your server. Once the file is in place, we want to adjust the values for DB_NAME, DB_USER, DB_PASSWORD and WP_HOME. Set their values to the ones you have defined in Part 1 of this article series.

In order to tell PHP about these new environment variables we will install the package vlucas/phpdotenv from Packagist

composer require vlucas/phpdotenv

Step 2: Modify the wp-config.php

Open our wordpress/wp-config.php file and edit the very beginning of the file. This part is crucial and essentially enables the use of any class from packages installed via Composer to be usable in WordPress.

wordpress/wp-config.php<?php/** @desc this loads the composer autoload file */require_once dirname( __DIR__ ) . '/vendor/autoload.php';/** @desc this instantiates Dotenv and passes in our path to .env */$dotenv = Dotenv\Dotenv::createImmutable(dirname(__DIR__));$dotenv->load();

Keep in mind, that wordpress/wp-config.php needs to be added to the preserve-paths section of your composer.json like we did in Part 1 of this article series. Otherwise you would loose your wp-config.php upon composer update.

Step 3: Using environment variables in PHP

WordPress (and its plugins) make heavy use of global constants which are set with define(). You can set them with values from our $_ENV variable. This variable holds all the key/value pairs from our .env file. In your wp-config.php replace the standard :

wordpress/wp-config.phpdefined('WORDPRESS_ENV') or define('WORDPRESS_ENV', $_ENV['WORDPRESS_ENV']);defined('WP_HOME') or define('WP_HOME', $_ENV['WP_HOME']);defined('DB_NAME') or define('DB_NAME', $_ENV['DB_NAME']);defined('DB_USER') or define('DB_USER', $_ENV['DB_USER']);defined('DB_PASSWORD') or define('DB_PASSWORD', $_ENV['DB_PASSWORD']);

It’s a good practice to test constants for their existence before defining them – this way you prevent a PHP warning should a constant be re-defined somewhere else. This is specially good advice when you are a Plugin author and use constants in your plugins’ code. If you don’t check for existence before defining it, one can’t define the constant in wp-config.php since that would cause the redefine error, which totally eliminates the benefits of having the constant in the first place.

Most plugin authors do it right, so now you can configure these plugin settings in your .env and wp-config.php. Take WooCommerce for example, to define that your websites’s front page shall be the main shop page:

.env#--------------------------------------------------------------------------------------------------##                                             PLUGINS                                              ##--------------------------------------------------------------------------------------------------## WooCommerce SHOP_IS_ON_FRONT=true

then in wp-config.php add:

wordpress/wp-config.phpdefined('SHOP_IS_ON_FRONT') or define('SHOP_IS_ON_FRONT', $_ENV['SHOP_IS_ON_FRONT']);

This changes the WooCommerce Homepage from http://example.com/shop/ to be on your front-page at http://example.com/ instead.

Step 4: Override Plugin Settings

Let’s say we want to configure transactional emails for our website. First we want a plugin, for example Mailgun Plugin for WordPress, so we install it with composer require wpackagist-plugin/mailgun.
Wordpress stores the settings in wp_options table, and it comes with a pre_option() filter, which allows us to override specific options directly in PHP like this:

wordpress/wp-content/themes/storefront-child/functions.php/** @desc override Mailgun settings and return API Credentials from .env file */if (is_plugin_active('mailgun/mailgun.php')) {    add_filter('pre_option_mailgun', 'override_mailgun_settings');    function override_mailgun_settings() : array {        return [            'region' => $_ENV['MAILGUN_REGION'],            'useAPI' => '0',            'domain' => $_ENV['MAILGUN_DOMAIN'],            'apiKey' => '',            'username' => $_ENV['MAILGUN_USER'],            'password' => $_ENV['MAILGUN_PASS'],            'secure' => '1',            'sectype' => 'tls',            'track-clicks' => 'htmlonly',            'track-opens' => '1',            'from-address' => $_ENV['MAILGUN_FROM'],            'from-name' => $_ENV['MAILGUN_FROMNAME'],            'override-from' => '1',            'campaign-id' => '',        ];    }}

The example above configures Mailgun SMTP from within my themes functions.php. In addition to the small function above we also add the few settings to the .env:

.envMAILGUN_REGION=euMAILGUN_DOMAIN=mg.example.comMAILGUN_USER=postmasterMAILGUN_PASS="myS3cretP4ss"MAILGUN_FROM="[email protected]"MAILGUN_FROMNAME="Customer Service"

This is how one overrides get_option calls. Plugins save either strings or serialised arrays in the wp_options table, so by unserializing that string you get the array that you want your custom override_plugin_settings() function to return.
Likewise you can override any other call to get_option(‘some-plugin-settings’); which allows us to basically configure plugins from within our projects’ code without the need of importing or making all these settings in the WordPress backend. If someone try to modify a plugins configuration in the backend this is usually ignored. The settings fields are sometimes grayed out.

Alternative: set environment variables in your Nginx.conf

Another option to define environment variables is to define environment variables in your Nginx configuration. Inside the location ~ \.php$ block of your configuration file you can also set environment variables like this:

/etc/nginx/sites-available/my-website.com.conffastcgi_param WORDPRESS_ENV production;fastcgi_param WP_HOME https://my-website.com;fastcgi_param WP_SITEURL https://my-website.com/;fastcgi_param WPLANG en_US;

These can the be accessed with $_SERVER[‘WORDPRESS_ENV’]; . Personally I prefer the .env file.

All the code discussed in this tutorial can be found in the following ZIP archive. Note that in order for the code to work as expected you need to rename the file from .env.dist to .env and edit your credentials.
Download Tutorial: Using an .env file for database and other credentials using-an-env-file-for-credentials.zip (30.8 MB)

Continue to the next tutorial Part 3 “Debugging WordPress in your development environment”.