Skip to content

Conversation

rsd
Copy link

@rsd rsd commented Sep 23, 2025

Why

Reusable modules need defaults while letting each app override. Today, when keys collide, module config wins.
Opt-in only; existing behavior unchanged unless providers call the new helper.

What

  • New Nwidart\Modules\Traits\ConfigMergerTrait
  • mergeConfigDefaultsFrom($path, $key, $existingPrecedence = true, $deep = true)
    • App (existing) config wins by default
    • Deep merge (default) via array_replace_recursive, or shallow via array_merge
    • No-op when config is cached

Usage (in a module ServiceProvider)

use Nwidart\Modules\Traits\ConfigMergerTrait;

class ModuleServiceProvider extends ServiceProvider
{
    use ConfigMergerTrait;

    protected function registerConfig(): void
    {
        $configPath = module_path($this->name, config('modules.paths.generator.config.path'));

        if (is_dir($configPath)) {
            $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($configPath));

            foreach ($iterator as $file) {
                if ($file->isFile() && $file->getExtension() === 'php') {
                    $config = str_replace($configPath.DIRECTORY_SEPARATOR, '', $file->getPathname());
                    $config_key = str_replace([DIRECTORY_SEPARATOR, '.php'], ['.', ''], $config);
                    $segments = explode('.', $this->nameLower.'.'.$config_key);

                    // remove duplicated adjacent segments
                    $normalized = [];
                    foreach ($segments as $segment) {
                        if (end($normalized) !== $segment) $normalized[] = $segment;
                    }

                    $key = ($config === 'config.php') ? $this->nameLower : implode('.', $normalized);

                    $this->publishes([$file->getPathname() => config_path($config)], 'config');
                    $this->mergeConfigDefaultsFrom($file->getPathname(), $key); // app wins (deep) by default
                }
            }
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant