Skip to content

Configuration

Samuel Gfeller edited this page Jan 3, 2024 · 11 revisions

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

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

Default values

The default and non-sensitive config values are inside config/defaults.php.
This file should contain all keys even when values are null to act as template that will be overwritten by the other configuration files.

Secret values

Environment-specific secret values are 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 env.dev.php. This file contains every non-secret configuration on the development machine such as error reporting and 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 to the env.test.php file.

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.

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).

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

# ...
env:
  APP_ENV: github
  
jobs:
  run:
    # ...

How configuration values are loaded

config/settings.php combines and returns all the relevant configuration files 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.).

Access 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 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 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');
    }
}
Clone this wiki locally