Search code examples
twigsmarty

Converting Smarty 3 templates to Twig 2, a few questions


I am converting some Smarty 3 templates over to Twig just to familiarize myself with Twig as it appears that Smarty 3 is being sparsely maintained (security issues haven't been fixed in releases).

There are a few different things in some of these Smarty templates that I haven't been able to figure out how to do with Twig yet:

This just lets us abstact the actual form code out of the loops so that if someone needs to edit the forms they dont have to go into the loops and mess with that.

{function editform zoneid='' zonename=''}
 ...html stuff that uses zoneid and zonename
{/function}
{function delform zoneid='' zonename=''}
 ...html stuff that uses zoneid and zonename
{/function}
{foreach from=$zn_array key=k item=val}
<tr><td>{val}</td><td>{editform zoneid=$k zonename=$val}</td><td>{delform zoneid=$k zonename=$val}</td></tr>
{/foreach}

Any idea how to make 'functions' in templates that can use 'variables' sent to them later in the template?


Solution

  • You can create macros:

    {% macro editform(zoneid, zonename) -%}
        Calling editform, zoneid is {{ zoneid|default('') }} and zonename is {{ zonename|default('') }}.
    {%- endmacro %}
    
    {% macro delform(zoneid, zonename) -%}
        Calling delform, zoneid is {{ zoneid|default('') }} and zonename is {{ zonename|default('') }}.
    {%- endmacro %}
    
    {% import _self as macros %}
    
    
    {% for k, val in zn_array %}
        <tr>
            <td>{{ val }}</td>
            <td>{{ macros.editform(k, val) }}</td>
            <td>{{ macros.delform(k, val) }}</td>
        </tr>
    {% endfor %}
    

    When zn_array is ['first', 'second', 'third'], the above produces this:

    <tr>
        <td>first</td>
        <td>Calling editform, zoneid is 0 and zonename is first.</td>
        <td>Calling delform, zoneid is 0 and zonename is first.</td>
    </tr>
    <tr>
        <td>second</td>
        <td>Calling editform, zoneid is 1 and zonename is second.</td>
        <td>Calling delform, zoneid is 1 and zonename is second.</td>
    </tr>
    <tr>
        <td>third</td>
        <td>Calling editform, zoneid is 2 and zonename is third.</td>
        <td>Calling delform, zoneid is 2 and zonename is third.</td>
    </tr>
    

    See TwigFiddle


    Some notes from the documentation:

    • Default argument values are defined by using the default filter in the macro body
    • Macros can be defined in any template, and need to be "imported" before being used
    • To import macros from the current file, use the special _self variable for the source (this is said in the documentation of the import tag)

    Note also that I used {%- and -%} (instead of just {% and %}) in strategic places to control whitespace so that the resulting HTML looks cleaner.


    You can change the import statement slightly so that you can omit the macros. prefix when calling the macros:

    {% from _self import editform, delform %}
    
    {{ editform(k, val) }}
    {{ delform(k, val) }}