dflydev / dflydev-dot-access-data

Given a deep data structure representing a configuration, access configuration by dot notation.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clobbering lacks support for merging non-associative array values

colinodell opened this issue · comments

Data::import(), Data::importData(), and Util::mergeAssocArray() support this notion of "clobbering" when trying to merge in two arrays. In a nutshell:

$clobber Value Behavior
false Values from the original array are preserved
true Values from the second array overwrite the first

For example:

$a = ['x' => 'a', 'foo' => ['foo'], 'a' => true];
$b = ['x' => 'b', 'foo' => ['bar'], 'b' => true];

Util::mergeAssocArray($a, $b, false);
// ['x' => 'a', 'foo' => ['foo'], 'a' => true, 'b' => true]

Util::mergeAssocArray($a, $b, true);
// ['x' => 'b', 'foo' => ['bar'], 'a' => true, 'b' => true]

However, there's no ability to merge non-associative array values. In the example above, it's impossible for me to have the foo key contain ['foo', 'bar').

To give a more realistic example, I might have Data elements representing HTML tag attributes:

$attributes = [
    'id' => 'logo',
    'class' => ['img-responsive'],
    'alt' => 'My logo',
];

And I want to merge in some additional attributes:

$more = [
    'class' => ['box-shadow'],
    'alt' => 'Our Awesome Logo',
];

In order to get this output:

[
    'id' => 'logo',
    'class' => ['img-responsive', 'box-shadow'],
    'alt' => 'Our Awesome Logo',
];

Unfortunately neither $clobber mode allows this.

Proposal

Add a third mode which acts more like PHP's array_merge() function - it will clobber things with string keys but append things with numeric keys.

To do this, we'll create three constants, one for each mode:

public const PRESERVE = 0; // equivalent to `false` in 1.x
public const REPLACE = 1; // equivalent to `true` in 1.x; default value
public const MERGE = 2; // the new approach I'm proposing

We'd also rename $clobber to $mode since it's no longer all-or-nothing.

This approach provides some level of backward-compatibility for anyone not using strict types, as false gets coerced to 0 and true gets coerced to 1.