2

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

fishbone
  • 3,140
  • 2
  • 37
  • 50

2 Answers2

2

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.

insertusernamehere
  • 23,204
  • 9
  • 87
  • 126
shawn
  • 4,305
  • 1
  • 17
  • 25
  • This doesn't explain why they say that associative arrays don't keep track of the order. So the benefit is not the ordering but the ability to modify it in loops – fishbone Mar 23 '18 at 09:32
0

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.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
  • It is not true, because php's array is implemented by Copy-On-Write. Passing arrays is as light as passing objects. – shawn Mar 23 '18 at 09:29
  • So try to modify and return that array from 10 different places. – Mike Doe Mar 23 '18 at 09:30
  • Please see my comment to shawn's answer – fishbone Mar 23 '18 at 09:33
  • There is only a few usages of OrderedHashMap in Symfony's codebase: https://github.com/symfony/form/search?utf8=%E2%9C%93&q=OrderedHashMap&type= The `children` is already `private`, no chance to trigger COW by different places. – shawn Mar 23 '18 at 09:34
  • What's a real world usage of passing an argument and doing nothing with it? – Mike Doe Mar 23 '18 at 09:50
  • Reading an array doesn't trigger COW. Passing an argument and reading it, very common. – shawn Mar 23 '18 at 10:00