inanepain/config

Configuration helpers.

Maintainers

Package info

github.com/inanepain/config

Homepage

Issues

pkg:composer/inanepain/config

Statistics

Installs: 10

Dependents: 2

Suggesters: 0

Stars: 1

0.4.0 2026-02-04 01:01 UTC

This package is auto-updated.

Last update: 2026-03-10 23:46:35 UTC


README

Table of Contents

icon inanepain/config

Configuration helpers.

1. Install

Example 1. composer

composer require inanepain/config

2. Config

The Inane\\Config\\Config class is a small helper built on top of Inane\\Stdlib\\Options. It is used to:

  • load configuration from a base config file

  • merge additional config files (via a glob_pattern)

  • (optionally) lock the configuration to prevent further modifications

  • provide a convention for component/class specific configuration via getConfig()

The public API is intentionally small:

  • Config::fromConfigFile() loads/merges/locks

  • Config::getConfig() returns a configuration subset for a specific class

2.1. Loading configuration from files

The default entry point is Config::fromConfigFile():

use Inane\Config\Config;

$config = Config::fromConfigFile();

By default it looks for config/app.config.php.

The base config file is expected to return an array (or something compatible with Options), e.g.:

// config/app.config.php

return [
    // the default key inspected by Config::fromConfigFile()
    'config' => [
        // Optional: extra files to merge in (glob brace patterns supported)
        'glob_pattern'        => 'config/autoload/{{,*.}global,{,*.}local}.php',

        // Optional: prevent modifications after initial loading
        'allow_modifications' => false,
    ],

    // application config (example)
    'appId'    => 'inane-fw',
    'services' => [
        // ...
    ],
];

If glob_pattern is set and matches files, each matching file is included and merged into the main config.

2.1.1. Config file merge order

The default glob_pattern merges *.global.php before \*.local.php allowing for default configurations to be overridden with local ones. It is recommended to have a .gitignore file in the autoload directory to ignore \*.local.php in your commits.

.gitignore for autoload directory
local.php
*.local.php

2.2. Locking and modifications

If allow_modifications is false (the default), Config::fromConfigFile() locks the configuration after loading/merging. This is a convenience to ensure your configuration is treated as immutable during runtime.

If you need a mutable config instance (for tests or dynamic environments), set:

return [
    'config' => [
        'allow_modifications' => true,
    ],
];

2.3. Component / class-specific configuration

Config::getConfig(string $class) is a convention for retrieving configuration scoped to a specific class.

By default, it looks under the components key and then under the given class name:

use Inane\Config\Config;

/** @var Config $config */
$serviceManagerConfig = $config->getConfig(Inane\Services\ServiceManager::class);

That means your config can be structured like this:

return [
    'components' => [
        Inane\Services\ServiceManager::class => [
            'cache' => true,
            'debug' => false,
        ],
    ],
];
Note getConfig() returns null when no matching config is found. If you rely on class-specific config injection (see ConfigAware below), ensure the config entry exists for that class, or use global injection instead.

:= ConfigManager

Inane\\Config\\ConfigManager is a small singleton that centralises configuration access and attribute-based injection.

It is primarily useful in bootstrapping code where you want to:

  • create/load one ConfigInterface instance (typically Config::fromConfigFile())

  • inject either global config or class-specific config into objects marked with #[ConfigAwareAttribute]

2.4. Creating and initialising the manager

The manager is a singleton:

use Inane\Config\Config;
use Inane\Config\ConfigManager;

$config = Config::fromConfigFile();

$configManager = ConfigManager::instance()
    ->setConfig($config);

If you don’t call setConfig() yourself, setConfigFor() will lazily initialise the manager with Config::fromConfigFile().

2.5. Injecting configuration into an object

ConfigManager::setConfigFor(object $object) inspects the object via reflection and looks for the ConfigAwareAttribute.

When found, it will call setConfig() on the object:

  • with the global config when the attribute requests global injection

  • otherwise with the config subset returned by Config::getConfig(<key>)

In the framework, this is used during bootstrapping (see Knot\\Application::bootstrapObject()).

Important Config::getConfig() returns null when no matching config is found. If you use class-specific injection, ensure you provide a matching entry under components.

2.6. Retrieving configuration from the manager

You can retrieve the manager’s configured ConfigInterface via getConfig().

use Inane\Config\ConfigManager;

$config = ConfigManager::instance()->getConfig();

When you pass a $key, the manager will first check that a configuration subset exists for that key. If it does not, it throws Inane\\Config\\Exception\\ConfigNotFoundException.

Note To actually use the subset, call Config::getConfig($key) directly on the returned config instance.

3. ConfigAware helpers

The ConfigAware helpers provide a lightweight, opt-in way to inject configuration into objects.

They are designed to work with Inane\\Config\\Config but can also accept plain arrays or Inane\\Stdlib\\Options.

3.1. Interface: ConfigAwareInterface

To be configurable, a class can implement Inane\\Config\\ConfigAware\\ConfigAwareInterface:

use Inane\Config\ConfigAware\ConfigAwareInterface;
use Inane\Stdlib\Array\OptionsInterface;

class MyComponent implements ConfigAwareInterface {
    public function setConfig(array|OptionsInterface $config): void {
        // store config / initialise component
    }
}

3.2. Trait: ConfigAwareTrait

Most classes will use the provided trait instead of implementing the storage/locking logic themselves.

The trait:

  • stores config in $this→config

  • merges the provided config with an optional $defaultConfig property

  • locks the config after it is set (to keep it effectively immutable)

Example:

use Inane\Config\ConfigAware\ConfigAwareInterface;
use Inane\Config\ConfigAware\ConfigAwareTrait;
use Inane\Stdlib\Array\OptionsInterface;

class MyComponent implements ConfigAwareInterface {
    use ConfigAwareTrait;

    // Optional: default/fallback config values
    protected array $defaultConfig = [
        'enabled' => true,
        'ttl'     => 60,
    ];

    public function isEnabled(): bool {
        return (bool)($this->config->enabled ?? false);
    }
}
Note ConfigAwareTrait::setConfig() only applies once: after the internal config is locked, subsequent calls have no effect.

3.3. Attribute: ConfigAwareAttribute

Inane\\Config\\ConfigAware\\ConfigAwareAttribute is a class attribute that can be used by a bootstrapper/container to decide how to inject configuration.

It has a single flag:

  • globalConfig=false (default): inject config scoped to the class via Config::getConfig(ClassName::class)

  • globalConfig=true: inject the global config instance as-is

Example — global config injection:

use Inane\Config\ConfigAware\ConfigAwareAttribute;
use Inane\Config\ConfigAware\ConfigAwareTrait;

#[ConfigAwareAttribute(true)]
class ServiceManager {
    use ConfigAwareTrait;
}

Example — class-specific injection:

use Inane\Config\ConfigAware\ConfigAwareAttribute;
use Inane\Config\ConfigAware\ConfigAwareTrait;

#[ConfigAwareAttribute]
class MyComponent {
    use ConfigAwareTrait;
}

With class-specific injection, ensure your configuration provides a matching entry under components:

return [
    'components' => [
        MyComponent::class => [
            'enabled' => true,
        ],
    ],
];
Important In the framework bootstrap implementation (see Knot\\Application::bootstrapObject()), when globalConfig=false the injector calls:

$object→setConfig($config→getConfig($object::class));

Since getConfig() can return null, class-specific injection requires that the class has a config entry. If you want a safe default without providing a components entry, prefer #[ConfigAwareAttribute(true)] and/or provide a $defaultConfig property on the class.

:= Exceptions

3.4. ConfigNotFoundException

Inane\\Config\\Exception\\ConfigNotFoundException is thrown when a requested configuration is missing.

It extends Inane\\Stdlib\\Exception\\ConfigurationException.

The exception is currently used by ConfigManager::getConfig($key) to fail fast when a class/component-specific configuration key does not exist.

use Inane\Config\ConfigManager;
use Inane\Config\Exception\ConfigNotFoundException;

try {
    // Validate that the component config exists
    $config = ConfigManager::instance()->getConfig(MyComponent::class);

    // Access the component-specific config via Config::getConfig()
    $componentConfig = $config->getConfig(MyComponent::class);
} catch (ConfigNotFoundException $e) {
    // handle missing configuration (provide defaults, abort startup, etc.)
}