Skip to content
This repository was archived by the owner on Jul 16, 2021. It is now read-only.
This repository was archived by the owner on Jul 16, 2021. It is now read-only.

ServiceProvider::mergeConfigFrom() change array_merge to array_replace_recursive #74

@anovix

Description

@anovix

Hi! We develop a package in our company and faced some issues with merging configuration files. Issue is just with array values.
E.g. Consider that we have a configuration file someConfig.php in our package, that may be like this:

return [
    'someArray' => [
        'key1' => 'value1',
        'key2' => 'value2',
    ],
];

Now when we want to override key1 with a different value, we create someConfig.php in applications config directory that looks like this:

return [
    'someArray' => [
        'key1' => 'value1OverriddenFromAppConfig',
    ],
];

When we dump the value of config('someConfig.someArray') it dumps just:

array:1 [▼
  "key1" => "value1OverriddenFromAppConfig"
]

So we loose the key2 from the package config and thus would need to define it again with same value or publish the whole config in the app. But I think it's better to see only overridden or added values in application config. That also prevents the need of changing all the not overridden values in application level config if a change is made in the package level config.

Another important issue is that after we have overridden values in the application level config and then added some new key and value in the package level config, we have to define the new key and value in all applications that use the config with some overridden keys from before.
Easy solution we used is to override Illuminate\Support\ServiceProvider::mergeConfigFrom() in our custom ServiceProvider and changed the method in a way that it now uses array_replace_recursive instead of array_merge.

protected function mergeConfigFrom($path, $key)
{
    $config = $this->app['config']->get($key, []);

    $this->app['config']->set($key, array_replace_recursive(require $path, $config));
}

This solves our problems flawlessly. E.g. In package config after adding new key:

return [
    'someArray' => [
        'key1' => 'value1',
        'key2' => 'value2',
        'keyAddedAfterSomeTime' => 'value',
    ],
];

And in our application config, we E.g. orverridde key1 and add some new key that is not defined in the package:

return [
'someArray' => [
        'key1' => 'value1OverriddenFromAppConfig',
        'keyAddedJustInAppConfig' => 'appConfigValue',
    ],
];

With array_replace_recursive we get all values we want:

array:4 [▼
  "key1" => "value1OverriddenFromAppConfig"
  "key2" => "value2"
  "keyAddedAfterSomeTime" => "value"
  "keyAddedJustInAppConfig" => "appConfigValue"
]

It also handles non array values correctly. I didn't find any problems with changing it to array_replace_recursive so we think it's a better solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions