22
votes

I have this in PHP:

$units = array();
foreach ($popPorts as $port) {
$units[$port->getFrameNo()][$port->getSlotNo()][$port->getPortNo()] = $port->getPortNo();
}

How can I achieve the same in twig?

I have tried this so far:

{% set frames = [] %}
{% for row in object.popPorts %}
    {% set frames[row.frameNo][row.slotNo][row.portNo] = row.portNo %}
{% endfor %}
{{ dump(frames) }}

But then I get an error:

Unexpected token "punctuation" of value "[" ("end of statement block" expected).

The output should be like this:

array (size=3)
  (frame) 1 => 
    array (size=2)
      (slot) 1 =>
        array (size=4)
          0 => (port) 26
          1 => (port) 27
          2 => (port) 28
          3 => (port) 29
      (slot) 5 =>
        array (size=2)
          0 => (port) 31
          1 => (port) 34
  (frame) 2 => 
    array (size=1)
      (slot) 3 =>
        array (size=1)
          0 => (port) 32
  (frame) 3 => 
    array (size=1)
      (slot) 6 =>
        array (size=1)
          0 => (port) 33
2
can you provide an example of your $units when it is done? because i could be that "row" has no key named "frameNo" - Ann-Sophie Angermüller
Doing this in twig will probably be annoying. You can use attribute for using a dynamic value as key, but not sure how it will work in nested structures. I would argue that converting types is logic that should be done in a Transformer/Converter class in your code and not in your template. - dbrumann
You cannot do that in twig, you need for example merge(). But although it is possible, but will lead to a lot of ugly code (you need temporary variables for your keys...). So if you can do it in php and send the result to twig, I would recommend that instead. - jeroen

2 Answers

40
votes

I'm afraid you can't create arrays like that in Twig. Even appending new items to an array is complicated because you need to create an array for the new element and concatenate it with the existing array. Example:

{% set array = [] %}
{% for item in items %}
    {% set array = array|merge([{ title: item.title, ... }]) %}
{% endfor %}

I know this looks awful, but all this inconvenience is done on purpose. Twig is meant to create templates, so the features available to create or process information are limited on purpose. The idea is that heavy data processing should be done with PHP.

24
votes

Another way :

{% set array = {
  'item-1': {
    'sub-item-1': 'my-sub-item-1',
    'sub-item-2': 'my-sub-item-2',
  },
  'item-2': {
    'sub-item-1': 'my-sub-item-1',
    'sub-item-2': 'my-sub-item-2',
  },
  'item-3': {
    'sub-item-1': 'my-sub-item-1',
    'sub-item-2': 'my-sub-item-2',
  }
}
%}