laminas/laminas-config-aggregator
Aggregate and merge configuration from multiple providers in Laminas/Mezzio apps. Supports ordered loading, caching, PHP/array and glob-based config files, and environment-specific overrides for fast, predictable configuration builds.
Installation:
composer require laminas/laminas-config-aggregator
For multi-format support (YAML, JSON, XML, INI):
composer require laminas/laminas-config
Basic Setup:
Create a config file (e.g., config/database.global.php):
return ['db' => ['dsn' => 'mysql:host=localhost']];
First Use Case:
use Laminas\ConfigAggregator\ConfigAggregator;
use Laminas\ConfigAggregator\PhpFileProvider;
$aggregator = new ConfigAggregator([
new PhpFileProvider('config/*.global.php'),
]);
$config = $aggregator->getMergedConfig();
// Use $config['db']['dsn'] in your app
PhpFileProvider for PHP files and LaminasConfigProvider for multi-format support.ConfigCacheProvider).Layered Configuration:
Use providers in a specific order (e.g., global.php, local.php, module.php) to override defaults:
$aggregator = new ConfigAggregator([
new PhpFileProvider('config/autoload/{,*.}global.php'),
new PhpFileProvider('config/autoload/{,*.}local.php'),
]);
Environment-Specific Configs:
Dynamically include environment files (e.g., dev.php, prod.php):
$aggregator = new ConfigAggregator([
new PhpFileProvider(sprintf('config/autoload/%s.php', $_ENV['APP_ENV'] ?? 'dev')),
]);
Module-Based Aggregation:
Treat each module as a provider (e.g., AuthModuleConfig::class):
class AuthModuleConfig {
public function __invoke() {
return ['auth' => ['driver' => 'oauth']];
}
}
Service Container: Bind the aggregator to Laravel’s container for dependency injection:
$app->singleton(ConfigAggregator::class, function ($app) {
return new ConfigAggregator([...]);
});
Caching: Cache merged configs in production:
use Laminas\ConfigAggregator\ConfigCacheProvider;
$cacheFile = storage_path('framework/config-cache.php');
$aggregator = new ConfigAggregator([
new ConfigCacheProvider($cacheFile, [
new PhpFileProvider('config/*.php'),
]),
]);
Validation:
Use post-processors to validate configs (e.g., with Respect\Validation):
$aggregator = new ConfigAggregator([...], null, [
function (array $config) {
$validator = new Validator();
$validator->validate($config, [
'db.dsn' => 'required|string',
]);
return $config;
},
]);
Dynamic Providers: Load providers conditionally (e.g., based on feature flags):
$providers = [];
if ($app->runningInConsole()) {
$providers[] = new PhpFileProvider('config/console/*.php');
}
Duplicate Providers:
Avoid duplicate class strings or instances—throws InvalidConfigProviderException:
// ❌ Throws exception
new ConfigAggregator([SomeProvider::class, SomeProvider::class]);
Globbing Quirks:
Laminas\Stdlib\Glob for cross-platform patterns (e.g., {dev,prod}.php).glob() if laminas-stdlib is missing.Precedence Order: Later providers override earlier ones. Test ordering carefully:
// 'local.php' overrides 'global.php'
new ConfigAggregator([
new PhpFileProvider('config/*.global.php'),
new PhpFileProvider('config/*.local.php'),
]);
Caching Caveats:
if (file_exists($cacheFile)) unlink($cacheFile);
var_dump($aggregator->getMergedConfig()) to debug precedence issues.ConfigCacheProvider to test live config changes.Custom Providers: Create providers for non-PHP sources (e.g., database, API):
class ApiConfigProvider {
public function __invoke() {
return json_decode(file_get_contents('https://api.example.com/config'), true);
}
}
Post-Processors for Transformations:
Convert configs to Laravel-specific formats (e.g., config('db.default')):
$aggregator = new ConfigAggregator([...], null, [
function (array $config) {
return collect($config)->mapWithKeys(fn ($value, $key) =>
['config.' . str_replace(['.', '[', ']'], '.', $key)] => $value
)->toArray();
},
]);
Environment Variables:
Replace placeholders (e.g., %DB_HOST%) with .env values:
$aggregator = new ConfigAggregator([...], null, [
function (array $config) {
return preg_replace_callback('/%([^%]+)%/', function ($matches) {
return env($matches[1], $matches[0]);
}, $config);
},
]);
yield per file).touch() config files on change).fgetcsv() for CSV configs) instead of loading entirely into memory.Service Provider Booting:
Register the aggregator in register() and bind configs in boot():
public function boot() {
$this->app->singleton('config', function () {
return new ConfigAggregator([...])->getMergedConfig();
});
}
Config Publishing:
Publish provider templates to config/:
$this->publishes([
__DIR__.'/config.php' => config_path('aggregator.php'),
]);
Environment Configs:
Override configs per environment (e.g., .env-based providers):
$aggregator = new ConfigAggregator([
new PhpFileProvider(sprintf('config/%s.php', $this->app->environment())),
]);
How can I help you explore Laravel packages today?