Configuration

Table of contents

Loading...

Introduction

The framework main files are located inside the directory config/.

The project environment configuration values are inside config/env/.

All configuration files are loaded in the config/settings.php file.

Default values

The default and non-sensitive config values are inside config/defaults.php.
This file should contain all keys even the ones that would hold secret values (set to null because the file is public) to act as template that will be overwritten by the other configuration files.

Secret values

Environment-specific secret values are stored in config/env/env.php.
This file should be added to the .gitignore file to not be pushed accidentally.

Environment specific non-secret values

Development

Development env values are in the file config/env/env.dev.php.
This file contains every non-secret configuration on the development machine such as the error reporting setting and the dev database name.
When testing, this file won't be loaded so everything relevant for testing that is not in or different from defaults.php should be defined in env.test.php.

Testing

The environment values for integration testing (e.g. database name) are stored inside config/env/env.test.php.

Production

Production env values are in the file config/env/env.prod.php. This file contains every non-secret configuration for the production environment on the remote server, for instance.

GitHub

The configuration values for the GitHub Actions CI/CD pipeline are in the file config/env/env.github.php. They load the env.test.php values with require (and not require_once because the values should be loaded for each test case, not only once) and may contain additional specific values for the GitHub environment such as other database credentials.

Setting the right environment

In order for the file settings.php to load the correct environment-specific values, the APP_ENV environment variable has to be set.

Production

For the production config values to be loaded, the following line has to be in the prod secret env.php:

$_ENV['APP_ENV'] = 'prod';

Testing

The APP_ENV environment variable for testing is set in the phpunit.xml file:

<!-- ... -->
    <php>
        <env name="APP_ENV" value="test"/>
    </php>
<!-- ... -->

Development

'dev' is the default fallback value for APP_ENV if it is not set.
The dev value should not be set anywhere because if it were in the env.php file of the development machine, it would overwrite the test value from the phpunit.xml file when testing.

GitHub

The APP_ENV environment variable for the GitHub Actions Build test is set in the workflow file.

File: .github/workflows/build.yml

# ...

jobs:
  run:
    steps:
      - name: Run test suite
        run: composer test
        env:
          APP_ENV: github
          PHP_CS_FIXER_IGNORE_ENV: 1

How configuration values are loaded

config/settings.php combines and returns all the relevant configuration file's values.

They are loaded in this order:

  1. File config/defaults.php
  2. File config/env/env.php
  3. Depending on what APP_ENV is defined, the environment-specific file is loaded (if APP_ENV is "test", it will load env.test.php, if it is "dev" it'll load env.dev.php and if it's "prod", it'll load env.prod.php etc.).

Accessing configuration values

Inside the container

The 'settings' key is defined in the DI container and can be accessed with $container->get('settings').

File: config/container.php

return [
    'settings' => function () {
        return require __DIR__ . '/settings.php';
    },
    LoggerInterface::class => function (ContainerInterface $container) {
        $loggerSettings = $container->get('settings')['logger'];
        // ...
    },
    // ...
];

Using the Settings class

In most files, the $container instance is not available and the configuration values have to be accessed with a utility class Settings.php.

It's not part of the domain logic (the core business logic), but rather supports the domain which is an infrastructure concern.

File: src/Infrastructure/Utility/Settings.php

<?php

namespace App\Infrastructure\Utility;

class Settings
{
    private array $settings;

    public function __construct(array $settings)
    {
        $this->settings = $settings;
    }

    public function get(string $key): mixed
    {
        return $this->settings[$key] ?? null;
    }
}

The Settings class is instantiated in the container.php file and added to the DI container.

File: config/container.php

// ...
Settings::class => function (ContainerInterface $container) {
    return new Settings($container->get('settings'));
},
// ...

The Settings class can now be injected into any class that needs to access a configuration value, and it can use the get() method to retrieve values from it.

File: src/Domain/Example/ExampleClass.php

<?php

namespace App\Domain\Example;

use App\Infrastructure\Utility\Settings;

class ExampleClass
{
    private array $exampleSettings;

    public function __construct(Settings $settings)
    {
        $this->exampleSettings = $settings->get('example_key');
    }
}
^