Why does Symfony provide an OrderedHashMap

605 Views Asked by At

Symfony provides an OrderedHashMap. Its documentation states

Unlike associative arrays, the map keeps track of the order in which keys were added and removed. This order is reflected during iteration.

I'm confused by this statement, because I thought PHP associative arrays are actually already ordered maps. I found this question on SO, which confirms my previous assumption: Are PHP Associative Arrays ordered?

I wonder, if the Symfony devs didn't know PHP arrays are already ordered maps or if I don't understand the role of Symfony's OrderedHashMap

2

There are 2 best solutions below

1
shawn On BEST ANSWER

Of course PHP's array is an ordered-map.

But Symfony's OrderedHashMap has some different behaviors (say, features) from PHP's array.

OrderedHashMap supports concurrent modification during iteration. That means that you can insert and remove elements from within a foreach loop and the iterator will reflect those changes accordingly. But array in the iteration is a copied one (Copy-On-Write), any modification is not reflected in the loop.

$map = new OrderedHashMap();
$map[1] = 1;
$map[2] = 2;
$map[3] = 3;

foreach ($map as $index => $value) {
    echo "$index: $value\n"
    if (1 === $index) {
        $map[1] = 4;
        $map[] = 5;
    }
}

You will get different output if you are using array. In the iteration of an array the loop won't see the number 5.

About "Why?": Search it in Symfony's codebase. There is only one place to use the OrderedHashMap, which is used to store a form's children. It's used by new InheritDataAwareIterator($this->children) to iterate. So I think the answer is to help to process the form's children.

And thanks to @fishbone:

So the benefit is not the ordering but the ability to modify it in loops.

6
Mike Doe On

In general, not only in Symfony's context, beside additional implemented features, object oriented structures are preferred over primitive types such as int, string or array as they can be injected into the class for unit testing.

Object oriented structures can enforce invariants as well whereas primitive types can only hold data without any behaviors.