2 minutes
Use dotenv to configure a Zend Expressive application
A new version of this article is available: Use Dotenv to Configure a Laminas or Mezzio Application.
This article is part of my #100DaysOfCode and #100DaysOfBlogging challenge. R1D6
[The Twelve-Factor App] requires strict separation of config from code.
Taken from factor three of The Twelve-Factor App.
Today I am studying about how to achieve this requirement making usage of phpdotenv in a Zend Expressive context.
I will not go into details on and advantages of this concept. A leave that up to other resources.
phpdotenv
This package
Loads environment variables from
.envtogetenv(),$_ENVand$_SERVERautomagically.
It has a clean setup and interface. To load an .env file use
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->load();
Then you can access it via
$s3Bucket = getenv('S3_BUCKET');
$s3Bucket = $_ENV['S3_BUCKET'];
$s3Bucket = $_SERVER['S3_BUCKET'];
The documentation mentions also the possibility to access variable through the request class. This is out-of-scope of this blog entry, since I want to access env vars only in configuration files.
Install phpdotenv
I install the package via Composer.
composer require vlucas/phpdotenv
Create a dotenv file
Next, I create a .env file.
DOCTRINE_CONNECTION_HOST="localhost"
DOCTRINE_CONNECTION_PORT="3306"
DOCTRINE_CONNECTION_USER="db_user"
DOCTRINE_CONNECTION_PASSWORD="my-53cr37"
DOCTRINE_CONNECTION_DBNAME="database"
DOCTRINE_CONNECTION_charset="utf8mb4"
Load dotenv
Now phpdotenv needs to be put to work and do its magic. In my index.php I add the following two lines right after requiring the composer autoload file.
$dotenv = Dotenv\Dotenv::create(__DIR__);
$dotenv->load();
Load configuration from dotenv
My configuration file with the database is updated, to use the env vars now available through getenv().
<?php
declare(strict_types = 1);
return [
    'doctrine' => [
        'connection' => [
            'orm_default' => [
                'params' => [
                    'host'     => getenv('DOCTRINE_CONNECTION_HOST'),
                    'port'     => getenv('DOCTRINE_CONNECTION_PORT'),
                    'user'     => getenv('DOCTRINE_CONNECTION_USER'),
                    'password' => getenv('DOCTRINE_CONNECTION_PASSWORD'),
                    'dbname'   => getenv('DOCTRINE_CONNECTION_DBNAME'),
                    'charset'  => getenv('DOCTRINE_CONNECTION_CHARSET'),
                ],
            ],
        ],
    ],
];
Goal accomplished
A quick check on my API confirms that the env vars are utilized correctly. 👍