<p>I think Marion chose a <em>great</em> name for her plugin—in her own words:</p>
<blockquote>
<p>Making Twig do things it really shouldn't. <strong>Twig is not intended to be a general purpose programming language</strong>, and there are some things that really don't belong in the language. This plugin adds a few of those things anyway.</p>
</blockquote>
<p>Emphasis added. <code>return</code> is a concept of languages that use functions to encapsulate bits of logic. Twig is an XML view layer that—in a perfect world—receives all the data it requires, and does minimal manipulation to that data before outputting it. Craft bends this paradigm a bit, because we often need to fetch additional elements, filter based on input/context, and so on… and it can get hairy, sometimes!</p>
<p>The best path forward is definitely moving this logic into a Twig <em>extension</em>, and/or a few <a href="https://craftcms.com/docs/5.x/extend/services.html" rel="nofollow noreferrer">services</a> designed to pre-process your data.</p>
<p>You have a couple of options:</p>
<ol>
<li>Spin up a new Twig extension with <a href="https://github.com/craftcms/generator/" rel="nofollow noreferrer">Generator</a>:
<pre class="lang-bash prettyprint-override"><code># Make a new module (or skip, if you have one already)
php craft make module
# Stub a Twig extension:
php craft make twig-extension --module=my-module
</code></pre>
Then, check out the documentation on <a href="https://craftcms.com/docs/5.x/extend/extending-twig.html" rel="nofollow noreferrer">extending Twig</a> to learn about adding functions, filters, and tags!</li>
<li>Use <a href="https://plugins.craftcms.com/twig-toolbox?craft5" rel="nofollow noreferrer">Twig Toolbox</a> to inject a function or two. (I wrote this for exactly the scenario you're describing!)</li>
</ol>
<p>Either option would allow you to pass off your Matrix data to a helper function, and receive a “munged” result:</p>
<pre><code>{% set myReport = toReport(entry.myMatrixField) %}
{% set myCards = toCards(entry.myMatrixField) %}
</code></pre>

CC BY-SA 4.0
2024-09-20T16:54:09.023Z
That _sounds_ incredibly helpful, August. Thank you! I will investigate :)
Jonathan Schofield
CC BY-SA 4.0
2024-09-20T16:28:18.257Z
2024-09-20T16:28:18.257Z
August Miller
<p>Check out my article <a href="https://nystudio107.com/blog/making-twig-macros-work-like-functions" rel="nofollow noreferrer">Making Twig Macros Work Like Functions</a> where it describes how you can return values from macros, includes, etc.</p>
<p>calculateSales.twig macro:</p>
<pre><code>{% set result = 0.0 %}
{% for order in orders %}
    {% set result = result + order['price'] * order['quantity'] %}
{% endfor %}
{{ result }}

</code></pre>
<p>...and then in your template:</p>
<pre><code>    {% set total = _self.calculateSales(orders) | spaceless | float %}

    &lt;span&gt;
        {{ total * 0.08 }}
    &lt;/span&gt;
</code></pre>

CC BY-SA 4.0
2024-09-22T10:36:23.703Z
Thanks Andrew. Looks like I could have done with reading that article *years ago*.
Jonathan Schofield
CC BY-SA 4.0
2024-09-23T17:13:39.613Z
Not your fault, the article didn't exist years ago :)
andrew.welch
CC BY-SA 4.0
2024-09-20T18:11:02.927Z
2024-09-20T18:11:02.927Z
andrew.welch
<p>August's answer is obviously the &quot;correct&quot; one. But I'm assuming if you're already prepared to get <em>that</em> dirty with Twig you wouldn't mind something like this: With <a href="https://twig.symfony.com/doc/3.x/tags/embed.html" rel="nofollow noreferrer">embed</a>, you can set variables in a parent template that are then available to the template doing the embedding. Combined with Twig's <a href="https://twig.symfony.com/doc/3.x/templates.html#whitespace-control" rel="nofollow noreferrer">whitespace trimmers</a> and <code>set...endset</code> you can effectively centralise and reuse a chunk of processing logic. Here's an example:</p>
<pre class="lang-twig prettyprint-override"><code>{# ==================================
_partials/processorLogic.twig:
===================================== #}

{% set mode = mode ?? 'regular' %}

{%- set someVariable -%}
    {# Add a vast amount of crazy logic here and save the output into someVariable. #}
    {% switch mode %}   
        {% case 'alt' %}        
            &lt;p&gt;Alt mode&lt;/p&gt;
        {% case 'regular' %}        
            &lt;p&gt;Regular mode&lt;/p&gt;
    {% endswitch %} 
{%- endset -%}

{# Placeholder to output stuff: #}
{% block content %}{% endblock %}

{# ==================================
Any other template:
===================================== #}

{% embed '_partials/processorLogic.twig' %}
    {% block content %}
        &lt;h1&gt;First instance of someVariable:&lt;/h1&gt;
        {{ someVariable }}
    {% endblock %}
{% endembed %}

{% embed '_partials/processorLogic.twig' with { mode: 'alt' } only %}
    {% block content %}
        &lt;h1&gt;Second instance of someVariable:&lt;/h1&gt;
        {{ someVariable }}
    {% endblock %}
{% endembed %}
</code></pre>

CC BY-SA 4.0
2024-09-20T17:38:19.570Z
Thanks James. I confess I’ve never got my head around practical use of embeds. I guess I should [flushed face emoji]
Jonathan Schofield
CC BY-SA 4.0
2024-09-23T10:18:32.297Z
Ah yep in my opinion everyone should be familiar with embeds. The Twig docs do a horrible job of attempting to explain them in my opinion. They're much simpler than they sound - it's really just a super-charged version of an `include`, which can be used when you need the calling template to pass in a lump of html. I use them extensively - mainly for my container partial: https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/templates/_partials/container.twig
James Smith
CC BY-SA 4.0
2024-09-20T17:02:06.287Z
2024-09-20T17:02:06.287Z
James Smith
<p>This may not be the best place for this, and quite probably I need to provide more context by way of example – so I will understand if it gets judged to be ‘not a proper question’ – but here goes…</p>
<h2>Background</h2>
<p>When I learned some years ago of Marion’s <a href="https://plugins.craftcms.com/twig-perversion" rel="nofollow noreferrer">Twig Perversion plugin</a> I found it to be a game changer to how I write templates:</p>
<p>For example:</p>
<ul>
<li>I frequently want to loop through elements and objects and update a hash which can then be deployed in multiple ways subject to context</li>
<li>The same compiled hash (which might itself be the outcome of iterating over myriad Matrix block macros) can subsequently be looped through to generate different ‘views’ of the content in the same page, such as:
<ul>
<li>A Matrix-derived sequence of multi-section content <em>and</em> a table of contents for it</li>
<li>Or a ‘report’ table which <em>also</em> generates a .csv or json of the same data.</li>
</ul>
</li>
</ul>
<p>So Twig Perversion's ability to <code>return</code> a <strong>variable</strong> from a macro instead of printing markup is invaluable.</p>
<p>I can probably dig out better examples of how I have been using this <code>return</code> ability, but here is a <a href="https://gist.github.com/watershed/3746fb96d87a5a7c5e0ce9db48300928" rel="nofollow noreferrer">Gist of ‘Reporting all fields in a Craft instance’</a>.</p>
<h2>Oh no!… fingers crossed</h2>
<p>A recent update to Twig <a href="https://github.com/marionnewlevant/craft-twig_perversion/issues/26#issuecomment-2344204688" rel="nofollow noreferrer">seemed to undermine</a> the on-going ability to do such ‘perverse’ things. As is so often the case, the inimitable Brandon may already have come up with a <a href="https://github.com/marionnewlevant/craft-twig_perversion/pull/27" rel="nofollow noreferrer">fix</a>. Which would be great.</p>
<h2>A way forward</h2>
<p>But the question arises whether using Twig Perversion to do the kind of thing I’m referring to above is <em>sensible</em>. Is it just storing up future templating fragility?</p>
<p>But I’m not sure how to go about engineering what I have become accustomed to doing without creating <em>incredibly verbose</em> templates.</p>
<p>Any thoughts or suggestions welcome.</p>

<templating><variable><macro>
Best template strategies as alternatives to `return`ing variables with Twig Perversion?
# Best template strategies as alternatives to `return`ing variables with Twig Perversion?

(Asked by: username_0 on 2024-09-20)

This may not be the best place for this, and quite probably I need to provide more context by way of example – so I will understand if it gets judged to be ‘not a proper question’ – but here goes…

## Background

When I learned some years ago of Marion’s [Twig Perversion plugin](https://plugins.craftcms.com/twig-perversion) I found it to be a game changer to how I write templates:

For example:

* I frequently want to loop through elements and objects and update a hash which can then be deployed in multiple ways subject to context
* The same compiled hash (which might itself be the outcome of iterating over myriad Matrix block macros) can subsequently be looped through to generate different ‘views’ of the content in the same page, such as:
  + A Matrix-derived sequence of multi-section content *and* a table of contents for it
  + Or a ‘report’ table which *also* generates a .csv or json of the same data.

So Twig Perversion's ability to `return` a **variable** from a macro instead of printing markup is invaluable.

I can probably dig out better examples of how I have been using this `return` ability, but here is a [Gist of ‘Reporting all fields in a Craft instance’](https://gist.github.com/watershed/3746fb96d87a5a7c5e0ce9db48300928).

## Oh no!… fingers crossed

A recent update to Twig [seemed to undermine](https://github.com/marionnewlevant/craft-twig_perversion/issues/26#issuecomment-2344204688) the on-going ability to do such ‘perverse’ things. As is so often the case, the inimitable Brandon may already have come up with a [fix](https://github.com/marionnewlevant/craft-twig_perversion/pull/27). Which would be great.

## A way forward

But the question arises whether using Twig Perversion to do the kind of thing I’m referring to above is *sensible*. Is it just storing up future templating fragility?

But I’m not sure how to go about engineering what I have become accustomed to doing without creating *incredibly verbose* templates.

Any thoughts or suggestions welcome.

**Tags:** templating, variable, macro

---

## 3 answers

### Answer by username_1 on 2024-09-20. Score: 4

I think Marion chose a great name for her plugin—in her own words:

Making Twig do things it really shouldn't. Twig is not intended to be a general purpose programming language, and there are some things that really don't belong in the language. This plugin adds a few of those things anyway.

Emphasis added. return is a concept of languages that use functions to encapsulate bits of logic. Twig is an XML view layer that—in a perfect world—receives all the data it requires, and does minimal manipulation to that data before outputting it. Craft bends this paradigm a bit, because we often need to fetch additional elements, filter based on input/context, and so on… and it can get hairy, sometimes!
The best path forward is definitely moving this logic into a Twig extension, and/or a few services designed to pre-process your data.
You have a couple of options:

Spin up a new Twig extension with Generator:
# Make a new module (or skip, if you have one already)
php craft make module
# Stub a Twig extension:
php craft make twig-extension --module=my-module

Then, check out the documentation on extending Twig to learn about adding functions, filters, and tags!
Use Twig Toolbox to inject a function or two. (I wrote this for exactly the scenario you're describing!)

Either option would allow you to pass off your Matrix data to a helper function, and receive a “munged” result:
{% set myReport = toReport(entry.myMatrixField) %}
{% set myCards = toCards(entry.myMatrixField) %}

> **Comments:**
> **username_0**: That _sounds_ incredibly helpful, August. Thank you! I will investigate :)  

---

### Answer by username_2 on 2024-09-20. Score: 2

Check out my article Making Twig Macros Work Like Functions where it describes how you can return values from macros, includes, etc.
calculateSales.twig macro:
{% set result = 0.0 %}
{% for order in orders %}
    {% set result = result + order['price'] * order['quantity'] %}
{% endfor %}
{{ result }}


...and then in your template:
    {% set total = _self.calculateSales(orders) | spaceless | float %}

    
        {{ total * 0.08 }}

> **Comments:**
> **username_0**: Thanks Andrew. Looks like I could have done with reading that article *years ago*.  
> **username_2**: Not your fault, the article didn't exist years ago :)  

---

### Answer by username_3 on 2024-09-20. Score: 1

August's answer is obviously the "correct" one. But I'm assuming if you're already prepared to get that dirty with Twig you wouldn't mind something like this: With embed, you can set variables in a parent template that are then available to the template doing the embedding. Combined with Twig's whitespace trimmers and set...endset you can effectively centralise and reuse a chunk of processing logic. Here's an example:
{# ==================================
_partials/processorLogic.twig:
===================================== #}

{% set mode = mode ?? 'regular' %}

{%- set someVariable -%}
    {# Add a vast amount of crazy logic here and save the output into someVariable. #}
    {% switch mode %}   
        {% case 'alt' %}        
            Alt mode
        {% case 'regular' %}        
            Regular mode
    {% endswitch %} 
{%- endset -%}

{# Placeholder to output stuff: #}
{% block content %}{% endblock %}

{# ==================================
Any other template:
===================================== #}

{% embed '_partials/processorLogic.twig' %}
    {% block content %}
        First instance of someVariable:
        {{ someVariable }}
    {% endblock %}
{% endembed %}

{% embed '_partials/processorLogic.twig' with { mode: 'alt' } only %}
    {% block content %}
        Second instance of someVariable:
        {{ someVariable }}
    {% endblock %}
{% endembed %}

> **Comments:**
> **username_0**: Thanks James. I confess I’ve never got my head around practical use of embeds. I guess I should [flushed face emoji]  
> **username_3**: Ah yep in my opinion everyone should be familiar with embeds. The Twig docs do a horrible job of attempting to explain them in my opinion. They're much simpler than they sound - it's really just a super-charged version of an `include`, which can be used when you need the calling template to pass in a lump of html. I use them extensively - mainly for my container partial: https://github.com/cld-agency/craftwind-boilerplate/blob/craft-4/templates/_partials/container.twig  

---

