Search code examples
phptwig

Problem creating JSON outuput in Twig Template


I'm learning to use the Craft CMS, which uses Twig templating. I'm trying to output a JSON object in Twig, but instead of 2 items in the JSON I'm getting info about a single item.

Here is my code:

{% set newsitems = craft.entries.section('newsitems').orderBy('PostDate desc').limit(100) %}

{% set response = [] %}
{% for newsitem in newsitems %}
    {{ 'Here' }}
    {% set response = response|merge({'type':0, 'id':newsitem.id, 'link':newsitem.sourceLink}) %}
{% endfor %}

{{ response|json_encode() }}

And here is the output I get:

Here Here {"type":0,"id":"25","link":"https:\/\/gadgets.ndtv.com"}

As can be seen, the loop executes two times ('Here' is printed 2 times) but there is only one item in the JSON array which is printed.

Am I missing something basic? Any help would be appreciated. Thanks in advance.


Solution

  • Twig's merge filter uses array_merge in the background.

    The manual states the following

    If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.

    This is what is happening to your output, in the first iteration you've create an associative array with the key: type, id, link. In the x'th iteration you are just overwriting the values stored in said keys. The solution is also stated in the manual, numeric indices will be appended to the array instead of overwriting it.

    In twig you would solve it as this:

    {% set response = [] %}
    {% for newsitem in newsitems %}
        {% set response = response|merge([{ 'type': 0, 'id': newsitem.id, 'source': newsitem.source,},]) %}
    {% endfor %}
    
    {{ response|json_encode|raw }}
    

    demo