<p><code>product</code> is not defined inside your macro. As the twig <a href="http://twig.sensiolabs.org/doc/tags/macro.html" rel="nofollow">macro</a> documentation says:</p>

<blockquote>
  <p>as with PHP functions, macros don't have access to the current template variables.</p>
</blockquote>

<p>So you will need to pass this one in:</p>

<pre><code>{% macro teaser(product, imgSize, className) %}
</code></pre>

<p>And when you call it:</p>

<pre><code>{{ m_product.teaser(product, 300, "product-teaser--in-list") }}
</code></pre>

<p>I would also add sensible defaults (if there are any that are sensible) for the macro arguments:</p>

<pre><code>{% macro teaser(product, imgSize=300, className='product-teaser--in-list') %}
</code></pre>

CC BY-SA 3.0
2016-07-22T15:23:19.520Z
Fantastic. Thanks Marion. This was the issue. I also had to pass in cart too. In this instance there is no sensible default, but this is a good idea to set this when it is required. Thanks again!
Terry Upton
CC BY-SA 3.0
2016-07-22T16:10:43.430Z
Out of interest is a macro the best use case for this situation, or would I have been better with an include and extend with and some vars?
Terry Upton
CC BY-SA 3.0
2016-07-22T19:39:44.483Z
I personally would probably use a macro, but an include could work well too.
Marion Newlevant
CC BY-SA 3.0
2016-07-22T15:16:56.760Z
2016-07-22T15:16:56.760Z
Marion Newlevant
<p>Yes! You have two things called <code>product</code>:</p>

<pre><code>{% for product in products %}
</code></pre>

<p>and</p>

<pre><code>{% import '_macros/_product' as product %}
</code></pre>

<p>What I would do is</p>

<pre><code>{% import '_macros/_product' as m_product %}
{{ m_product.teaser(300, "product-teaser--in-list") }}
</code></pre>

CC BY-SA 3.0
2016-07-22T14:52:35.593Z
Thanks Marion. However, having changed this as suggested. I still get the same error I am afraid.
Terry Upton
CC BY-SA 3.0
2016-07-22T15:10:12.383Z
I still think this is a good idea, but as Terry says, not at all his problem
Marion Newlevant
CC BY-SA 3.0
2016-07-22T14:48:16.480Z
2016-07-22T14:48:16.480Z
Marion Newlevant
<p>I have tried to setup the following Macro to reuse code for product teasers across my site. The macros looks like this;</p>

<pre><code>{% macro teaser(imgSize, className) %}
    &lt;div class="product-teaser{% if className %} // {{ className }}{% endif %}"&gt;
        {% import '_macros/_img' as m_img %}
        {% set thumbAsset = product.productImage.first() %}
        &lt;a href="{{ product.url }}"&gt;
            {{ m_img.fixedSize(thumbAsset, imgSize, {alt: product.title, class: 'product-teaser__img' }) }}
        &lt;/a&gt;
        &lt;h3 class="product-teaser__title{% if className %} // {{ className }}__title{% endif %}"&gt;{{ product.title }}&lt;/h3&gt;
        &lt;p class="product-teaser__price{% if className %} // {{ className }}__price{% endif %}"&gt;{{ product.defaultPrice|currency(cart.currency) }}&lt;/p&gt;

        &lt;p&gt;
            &lt;a href="{{ product.url }}" class="btn // btn--sub"&gt;View Product&lt;/a&gt;
            {# &lt;a href="" class="btn // btn--base"&gt;Canine Range&lt;/a&gt; #}
        &lt;/p&gt;
    &lt;/div&gt;
{% endmacro %}
</code></pre>

<p>and an example to call it like this:</p>

<pre><code>{% set products = craft.commerce.products.relatedTo(category)%}
{% for product in products %}
    {% import '_macros/_product' as product %}
    {{ product.teaser(300, "product-teaser--in-list") }}
{% endfor %}
</code></pre>

<p>However, the error I get back is </p>

<blockquote>
  <p>Variable "product" does not exist</p>
</blockquote>

<p>Any idea what I am doing wrong?</p>

<p>EDIT: just to add a bit more feedback. The full error is:
<a href="https://i.sstatic.net/Vub44.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Vub44.png" alt="enter image description here"></a></p>

<macro>
Help with Macros
# Help with Macros

(Asked by: username_0 on 2016-07-22)

I have tried to setup the following Macro to reuse code for product teasers across my site. The macros looks like this;
{% macro teaser(imgSize, className) %}
    
        {% import '_macros/_img' as m_img %}
        {% set thumbAsset = product.productImage.first() %}
        
            {{ m_img.fixedSize(thumbAsset, imgSize, {alt: product.title, class: 'product-teaser__img' }) }}
        
        {{ product.title }}
        {{ product.defaultPrice|currency(cart.currency) }}

        
            View Product
            {# Canine Range #}
        
    
{% endmacro %}

and an example to call it like this:
{% set products = craft.commerce.products.relatedTo(category)%}
{% for product in products %}
    {% import '_macros/_product' as product %}
    {{ product.teaser(300, "product-teaser--in-list") }}
{% endfor %}

However, the error I get back is 

Variable "product" does not exist

Any idea what I am doing wrong?
EDIT: just to add a bit more feedback. The full error is:

**Tags:** macro


---

## 2 answers

### Answer by username_1 on 2016-07-22. Score: 2 | Accepted answer

product is not defined inside your macro. As the twig macro documentation says:

as with PHP functions, macros don't have access to the current template variables.

So you will need to pass this one in:
{% macro teaser(product, imgSize, className) %}

And when you call it:
{{ m_product.teaser(product, 300, "product-teaser--in-list") }}

I would also add sensible defaults (if there are any that are sensible) for the macro arguments:
{% macro teaser(product, imgSize=300, className='product-teaser--in-list') %}

> **Comments:**
> **username_0**: Fantastic. Thanks Marion. This was the issue. I also had to pass in cart too. In this instance there is no sensible default, but this is a good idea to set this when it is required. Thanks again!  
> **username_0**: Out of interest is a macro the best use case for this situation, or would I have been better with an include and extend with and some vars?  
> **username_1**: I personally would probably use a macro, but an include could work well too.  

---

### Answer by username_1 on 2016-07-22. Score: 2

Yes! You have two things called product:
{% for product in products %}

and
{% import '_macros/_product' as product %}

What I would do is
{% import '_macros/_product' as m_product %}
{{ m_product.teaser(300, "product-teaser--in-list") }}

> **Comments:**
> **username_0**: Thanks Marion. However, having changed this as suggested. I still get the same error I am afraid.  
> **username_1**: I still think this is a good idea, but as Terry says, not at all his problem  

---

