<p>A little bit late but maybe someone else has the same issue and want's to accomplish this.
You can use this Plugin <a href="https://github.com/marionnewlevant/craft-twig_perversion/tree/v1" rel="noreferrer">Twig Perversion</a> to create macros that return values</p>

<pre><code>{% macro getParentEntry(thisEntry) %}
    {% import _self as self %}
    {% if thisEntry.parent|length %}
        {% set parent = thisEntry.parent %}
    {% else %}
        {% set parent = false %}
    {% endif %}
    {% return parent %}
{% endmacro %}
</code></pre>

<p>And you can use it with </p>

<pre><code>{% set parent = self.getParentEntry( entry ) %}
</code></pre>

CC BY-SA 3.0
2017-12-13T15:00:21.603Z
2017-12-14T18:38:27.333Z
2017-12-14T18:38:27.333Z
Robin Schambach
<p>I think the issue with trying to set a variable in a macro is that the variable is limited to the scope of the macro you are triggering, so <code>{% set parent = thisEntry %}</code> is available within the scope of your macro, but doesn't define it for the rest of your template.</p>

<blockquote>
  <p>Macros are comparable with functions in regular programming languages. They are useful to put often used HTML idioms into reusable elements to not repeat yourself.  </p>
  
  <p>Macros differs from native PHP functions in a few ways:</p>
  
  <ul>
  <li>Default argument values are defined by using the default filter in the macro body;  </li>
  <li>Arguments of a macro are always optional.</li>
  <li>But as with PHP functions, <strong>macros don't have access to the current template variables</strong>.</li>
  </ul>
</blockquote>

<p><a href="http://twig.sensiolabs.org/doc/tags/macro.html">Taken from the Twig docs</a></p>

<p>So due to the limitations in scope and the nature of macros, they are meant to be used to just output reusable code, not set and define logic in your templates. So everything is just rendered as a string (models have their <code>__toString()</code> method called)</p>

<p>The way you could get this to work for you is to just output whether or not the logic in your macro is true or null, then do the rest of the logic in your template, something like:</p>

<pre><code>{% macro hasParentEntry(thisEntry) %}

 {% import _self as self %}

 {% if thisEntry.parent|length %}

   {# would output 1 #}
   {{ true }}

 {% else %}

   {# or just output null #}
   {{ null }}

 {% endif %}

{% endmacro %}
</code></pre>

<p>Then in your template do something like:</p>

<pre><code>{# This will either be true or null #}
{% set parent = self.hasParentEntry( entry ) %}

{% if parent %}

 {# this will set your parent variable to the entry model or leave the variable as null #}
 {% set parent = entry.parent %}

{% endif %}
</code></pre>

CC BY-SA 3.0
2015-06-09T16:26:14.610Z
Great explanation. And a very useful suggestion given the limitations. Thanks alot Alec!
bravokiloecho
CC BY-SA 3.0
2015-06-09T19:01:16.517Z
Not a problem @negatron :)
Alec Ritson
CC BY-SA 3.0
2015-06-09T13:10:45.130Z
2015-06-09T13:10:45.130Z
Alec Ritson
<p>Is there any way to use a macro in twig to define a variable outside that macro?</p>

<p>For example, say you want to use a macro to set a variable that stores an entry's parent (I know you can do this much simply, but I have my reasons to want to do it like this), I would intuitively want to do something like this:</p>

<pre><code>{% macro getParentEntry(thisEntry) %}

    {% import _self as self %}

    {% if thisEntry.parent|length %}

        {% set parent = thisEntry %}

    {% else %}

        {% set parent = false %}

    {% endif %}

{% endmacro %}

{% import _self as self %}
{% set parent = self.getParentEntry( entry ) %}
</code></pre>

<p>But this clearly isn't quite right.</p>

<p>Am I missing something, or is this just not possible. (I couldn't find any mention of anything like this in the twig documentation.)</p>

<p>Many thanks!</p>

<templating><variable><macro>
Use a Twig macro to set a variable
# Use a Twig macro to set a variable

(Asked by: username_0 on 2015-06-09)

Is there any way to use a macro in twig to define a variable outside that macro?
For example, say you want to use a macro to set a variable that stores an entry's parent (I know you can do this much simply, but I have my reasons to want to do it like this), I would intuitively want to do something like this:
{% macro getParentEntry(thisEntry) %}

    {% import _self as self %}

    {% if thisEntry.parent|length %}

        {% set parent = thisEntry %}

    {% else %}

        {% set parent = false %}

    {% endif %}

{% endmacro %}

{% import _self as self %}
{% set parent = self.getParentEntry( entry ) %}

But this clearly isn't quite right.
Am I missing something, or is this just not possible. (I couldn't find any mention of anything like this in the twig documentation.)
Many thanks!

**Tags:** templating, variable, macro

---

## 2 answers

### Answer by username_2 on 2015-06-09. Score: 12 | Accepted answer

I think the issue with trying to set a variable in a macro is that the variable is limited to the scope of the macro you are triggering, so {% set parent = thisEntry %} is available within the scope of your macro, but doesn't define it for the rest of your template.

Macros are comparable with functions in regular programming languages. They are useful to put often used HTML idioms into reusable elements to not repeat yourself.  
Macros differs from native PHP functions in a few ways:

Default argument values are defined by using the default filter in the macro body;  
Arguments of a macro are always optional.
But as with PHP functions, macros don't have access to the current template variables.


Taken from the Twig docs
So due to the limitations in scope and the nature of macros, they are meant to be used to just output reusable code, not set and define logic in your templates. So everything is just rendered as a string (models have their __toString() method called)
The way you could get this to work for you is to just output whether or not the logic in your macro is true or null, then do the rest of the logic in your template, something like:
{% macro hasParentEntry(thisEntry) %}

 {% import _self as self %}

 {% if thisEntry.parent|length %}

   {# would output 1 #}
   {{ true }}

 {% else %}

   {# or just output null #}
   {{ null }}

 {% endif %}

{% endmacro %}

Then in your template do something like:
{# This will either be true or null #}
{% set parent = self.hasParentEntry( entry ) %}

{% if parent %}

 {# this will set your parent variable to the entry model or leave the variable as null #}
 {% set parent = entry.parent %}

{% endif %}

> **Comments:**
> **username_0**: Great explanation. And a very useful suggestion given the limitations. Thanks alot Alec!  
> **username_2**: Not a problem @negatron :)  

---

### Answer by username_1 on 2017-12-13. Score: 9

A little bit late but maybe someone else has the same issue and want's to accomplish this.
You can use this Plugin Twig Perversion to create macros that return values
{% macro getParentEntry(thisEntry) %}
    {% import _self as self %}
    {% if thisEntry.parent|length %}
        {% set parent = thisEntry.parent %}
    {% else %}
        {% set parent = false %}
    {% endif %}
    {% return parent %}
{% endmacro %}

And you can use it with 
{% set parent = self.getParentEntry( entry ) %}


---

