Issues

ZF2-186: Config::merge() replacing numeric config settings

Issue Type: Bug Created: 2012-03-03T10:06:05.000+0000 Last Updated: 2012-03-03T13:40:56.000+0000 Status: Resolved Fix version(s): Reporter: Artur Bodera (joust) Assignee: Artur Bodera (joust) Tags: - Zend\Config

  • Config
  • merge

Related issues: Attachments:

Description

h3. The problem In a scenario, where a config value is a numerical list (numerical array), Config::merge() overwrites individual items in the source list instead of appending to it.

h3. Real-world scenario Config is probably most often used to configure components and modules. Numeric keys are rarely used, but if present, usually describe a list of possible items.

An example for that could be a Navigation container. A Navigation container is configured by an ordered list (i.e. numerical array) describing different pages. Let's assume that ModuleA provides a list of pages, and ModuleB provides its own list of pages.

When merging two Config objects from two different modules, the items (pages) from ModuleB will override (replace pages) from ModuleA, which is not an expected behavior.

h3. Sample script

<pre class="highlight">

$arrayA = array(
    'flag' => true,
    'text' => 'foo',
    'list' => array( 'a', 'b', 'c' ),
    'aSpecific' => 12
);

$arrayB = array(
    'flag' => false,
    'text' => 'bar',
    'list' => array( 'd', 'e' ),
    'bSpecific' => 100
);

$configA = new Config($arrayA);
$configB = new Config($arrayB);

$configA->merge($configB); // merge B onto A

$expectedMergeResult = array(
    'flag' => false,
    'text' => 'bar',
    'list' => array( 'a', 'b', 'c', 'd', 'e' ),
    'aSpecific' => 12,
    'bSpecific' => 100
);

h3. How does it work outside of ZF? In pure PHP implementation, the primary difference between array_merge_recursive() and array_replace_recursive() is that _merge will append (extend) nested, numerical arrays. The other function, _replace, will override numerical values. Config::merge() method does perform similar operation to array_replace_recursive() but does not provide any means to select a behavior for handling lists.

h3. The solution The default Config::merge() behavior needs to be compatible with array_merge_recursive() - i.e. it has to recognize lists and append their values. For cases when one needs to have a replace behavior, a separate function will be provided - Config::replace()

h3. Differences between Config::merge() and array_merge_recursive()

The most important difference between those functions is how they handle string values.

Let's assume we have following arrays:

<pre class="highlight">
$arrayA = array( 'foo' => 1, 'bar' => 'text' );
$arrayB = array( 'bar' => 'other text' );

When given duplicate keys and string values array_merge_recursive() will create an array of values:

<pre class="highlight">
print_r(array_merge_recursive($arrayA,$arrayB));
// Array
//(
//    [foo] => 1
//    [bar] => Array
//        (
//            [0] => text
//            [1] => other text
//        )
//
//)

With duplicate keys Config::merge() will overwrite the value, regardless of its type :

<pre class="highlight">
$configA = new Config($arrayA);
$configB = new Config($arrayB);
$configA->merge($configB);

print_r($configA->toArray());
// Array
//(
//    [foo] => 1
//    [bar] => other text
//)

Comments

Posted by Artur Bodera (joust) on 2012-03-03T13:40:56.000+0000

Fixed in https://github.com/zendframework/zf2/pull/880

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts