domsson domsson - 6 months ago 143
Twig Question

"Illegal offset type in isset or empty" when using a Twig macro

Using Grav v1.3.8 (running on PHP 5.6.30), I'm currently getting a Server error ("Illegal offset type in isset or empty") when trying to render a Twig template that is using a macro.

What's interesting is that this only happens when I use the macro by itself. As soon as I append a filter, like

trim
, everything works as expected.

The (shortened) macro file,
helpers.twig
:


{% macro ascii(str) %}
{% spaceless %}
{{ str|replace({
'Á': 'A',
'À': 'A',
'Â': 'A',
'Ã': 'A',
....
'ƒ': 'f'
})
}}
{% endspaceless %}
{% endmacro ascii %}


The template (MCVE):

{% import 'macros/helpers.twig' as helpers %}

{% set img = helpers.ascii('günter-berger.jpg') %}
{% if page.media[img] is defined %}
<img src="{{ page.media[img].url }}">
{% endif %}


This will produce the error. I narrowed it down to the
if
line. Apparently, the macro is working fine, but the condition will throw an error if fed the output of it, unfiltered. Adding any filter, like
trim
or
lower
, will get it to work again.

In other words, these work:


  • {% if page.media['günter-berger.jpg'] is defined %}

  • {% if page.media[helpers.ascii('günter-berger.jpg')|trim] is defined %}



But this will throw an error:


  • {% if page.media[helpers.ascii('günter-berger.jpg')] is defined %}



However, trying the same thing on twigfiddle, all three seem to work there.

Maybe an issue with Grav? Can someone point out any possible causes?

Answer Source

I forgot this, but a macro does not return a string but instead returns an instance of a Twig_Markup

{% set test = macro.ascii('Ghünter.jpg') %}
{{ dump(test) }}

Output : object(Twig_Markup)#10679 (2) { ["content":protected]=> string(11) "Ghunter.jpg" ["charset":protected]=> string(5) "UTF-8" }

Because the return type is an object you get this notification as you can't use objects as index. By using a filter on this instance, the magic method __toString method will be called, causing it to return a string, thus making it useable as index for an array

The only was to bypass this, would be writing a filter instead of a macro

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download