Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Settings and environment

An application has values that differ between your computer and the server: the database password, debug mode, the site name. They are not written directly into code. Such values are kept in a .env file, and the code reads them from one place — the settings array.

Installation

The .env file is read by the phpdotenv package:

composer require vlucas/phpdotenv

The .env file

Create a .env file by hand in the project root, next to composer.json:

APP_DEBUG=true
SITE_NAME="My blog"

Each line is a name and a value. These are environment variables: on another server the same file holds different values.

Loading

The file is loaded in config/bootstrap.php, right after the autoloader:

// config/bootstrap.php
require __DIR__ . '/../vendor/autoload.php';
 
Dotenv\Dotenv::createImmutable(__DIR__ . '/..')->safeLoad();

After this line the values are available in the $_ENV array. The safeLoad() method does not throw if the file is missing — on a server the variables may be set another way.

The settings array

Create config/settings.php. It is the only place where code touches $_ENV:

// config/settings.php
return [
    'debug' => filter_var($_ENV['APP_DEBUG'] ?? false, FILTER_VALIDATE_BOOL),
    'site_name' => $_ENV['SITE_NAME'] ?? 'Blog',
];

The file returns a plain array. Values from .env are always strings, so filter_var() turns the string true or false into a boolean.

Settings in the container

To make the settings available to the rest of the application, add them to config/container.php under the name settings:

// config/container.php
return [
    'settings' => fn () => require __DIR__ . '/settings.php',
];

The other entries of the file stay in place — one line is added.

Using them

The container cannot supply a plain value by itself: the string type does not say which string is wanted. So a class that needs a setting gets a definition:

// config/container.php
use App\Action\HomeAction;
use Psr\Container\ContainerInterface;
 
return [
    'settings' => fn () => require __DIR__ . '/settings.php',
 
    HomeAction::class => fn (ContainerInterface $c) => new HomeAction(
        $c->get('settings')['site_name'],
    ),
];
// src/Action/HomeAction.php
final class HomeAction
{
    public function __construct(private string $siteName) {}
 
    public function __invoke(Request $request, Response $response): Response
    {
        $response->getBody()->write($this->siteName);
 
        return $response;
    }
}

The home page shows "My blog". Change SITE_NAME in .env and reload the page — the text changes without touching the code.

The example file

Passwords will appear in .env later, so it is not added to version control — put .env into the .gitignore file. Next to it keep .env.example with the same names but without secret values: it shows which variables the project needs.

Common mistake

Writing (bool) $_ENV['APP_DEBUG'] does not work as expected: the string false is not empty, and PHP treats it as true. Debug mode ends up enabled on the server. For boolean values use filter_var(..., FILTER_VALIDATE_BOOL).

Thanks for reading!

Donate to the site — we work hard for you.