I'm trying to use the json_decode twig filter from Craft to decode an array of entry objects that got encoded in a macro.
In the macro, the array of entry objects gets encoded by json_encode and echoed:
{{ orderedFutureEvents|json_encode }} This is how the macro value gets set in the template:
{% set events = craft.entries() .section('eventPost') .all() %} {% import "_macros/events.html" as eventsMacro %} {% set futureEvents %} {{ eventsMacro.futureEvents(events)|json_decode }} {% endset %} When loading the page it's used on, I get a syntax error:
Invalid Argument – yii\base\InvalidArgumentException
Syntax error.
The specific lines that trows the error:
yiisoft/yii2/helpers/BaseJson.php at line 133
yiisoft/yii2/helpers/BaseJson.php at line 107
Compiled template line:
$context["test"] = craft\helpers\Json::decode((isset($context["futureEvents"]) || array_key_exists("futureEvents", $context) ? $context["futureEvents"] : (function () { throw new RuntimeError('Variable "futureEvents" does not exist.', 19, $this->source); })())); What's causing this error?
Full macro:
{% macro futureEvents(events) %} {% set today = "now"|date('d/m/Y') %} {% set now = "now"|date('U') %} {% set futureEvents = [] %} {% for event in events %} {% for block in event.calendar.level(1).all() %} {% switch block.type.handle %} {% case 'periodOfDays' %} {% if block.endDate|date('d/m/Y') > today %} {% if block.startDate|date('d/m/Y') < today %} {# Ongoing event #} {% set futureEvents = futureEvents|merge([{'date': today, 'event': event}]) %} {% else %} {# Future event #} {% set futureEvents = futureEvents|merge([{'date': block.startDate|date('d/m/Y'), 'event': event}]) %} {% endif %} {% endif %} {% case 'specificDates' %} {% set tempEvent = [] %} {% set break = false %} {% set empty = false %} {% for child in block.children.all() if not break %} {% if child.dateAndTime|date('U') > now %} {# Future event #} {% set tempEvent = [{'date': child.dateAndTime|date('d/m/Y'), 'event': event}] %} {% set break = true %} {# Break because event is found #} {% elseif (child.dateAndTime|date('U') + child.duration*60) > now %} {# Ongoing event #} {% set tempEvent = [{'date': today, 'event': event}] %} {% set break = true %} {# Break because event is found #} {% endif %} {% else %} {% set empty = true %} {% endfor %} {% if tempEvent is same as([]) and empty %} {# Fallback on default #} {% elseif tempEvent is not same as([]) %} {% set futureEvents = futureEvents|merge(tempEvent) %} {% endif %} {% endswitch %} {% else %} {% if event.dateAndTime|date('U') > now %} {# Future event #} {% set futureEvents = futureEvents|merge([{'date': event.dateAndTime|date('d/m/Y'), 'event': event}]) %} {% elseif (event.dateAndTime|date('U') + event.duration*60) > now %} {# Ongoing event #} {% set futureEvents = futureEvents|merge([{'date': today, 'event': event}]) %} {% endif %} {% endfor %} {% endfor %} {% set orderedFutureEvents = [] %} {% for key in futureEvents|sort((a, b) => a <=> b)|column('date', 'event')|keys %} {% set orderedFutureEvents = orderedFutureEvents|merge([futureEvents[key].event]) %} {% endfor %} {{ orderedFutureEvents|json_encode|raw }} {% endmacro %}
orderedFutureEventsis an array of entries that you JSON encode into a string. Iseventsin your macro the same JSON encodedorderedFutureEventsthat gets passed into the macro?eventsparameter is an array of entry objects. The macro filters out specific entries to return a new array of entry objects. I'll update my post to make it a bit more clear.