<p>Your syntax is close, but not quite right and you're setting a variable as a string and later setting it as an Element Model. I think you're searching for something closer to this:</p>

<pre><code>{% macro firstImage(entry) %}

    {% if entry.sliderMatrix.total() %}
        {% set block = entry.sliderMatrix.first %}
        {% set image = block.image.first %}
    {% endif %}

    {% if image is defined and image %}
        {{ image.url }}
    {% endif %}

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

CC BY-SA 3.0
2015-03-17T21:14:20.470Z
This syntax is much better! May I suggest `if image is defined`?
Lindsey D
CC BY-SA 3.0
2015-03-17T21:14:45.300Z
You surely may :-)
Peter Tell
CC BY-SA 3.0
2015-03-17T22:43:37.140Z
@Christian if that asset field is not marked as required you should also check if `first()` actually returns an image, so use this conditional `{% if image is defined and image %}`.
carlcs
CC BY-SA 3.0
2015-03-18T08:10:28.863Z
Even if that asset field **is** marked as required you should still check if `first()` actually returns an image. If that required image is deleted after the entry is created you will end up with an entry with no image.
Marion Newlevant
CC BY-SA 3.0
2015-03-17T21:11:15.543Z
2015-03-18T11:20:16.780Z
2015-03-18T11:20:16.780Z
Peter Tell
<p>Hard to say for sure, but here's what I suspect... You may have multiple instances of <code>firstImage</code> being called from your main template.</p>

<p>For some of those instances, <code>entry.sliderMatrix.total</code> is <strong>greater than</strong> zero. For other instances, <code>entry.sliderMatrix.total</code> is <strong>equal to</strong> zero. And of course, when <code>entry.sliderMatrix.total</code> is equal to zero, your <code>if</code> statement will be bypassed.</p>

<p>Realistically, you shouldn't have the <code>image.url</code> call outside of your <code>if</code> statement. Because any time the <code>if</code> statement evaluates to <em>false</em>, then the <code>image</code> variable won't be what you want it to be. In fact, you'll get that exact error, since <code>image</code> will still be set to a string.</p>

CC BY-SA 3.0
2015-03-17T21:12:43.477Z
2015-03-17T21:12:43.477Z
Lindsey D
<p>I've written a short macro to get the first image inside a matrix field.</p>

<pre><code>{% macro firstImage(entry) %}

    {% set image = 'hello' %}

    {% if entry.sliderMatrix.total() %}
        {% set block = entry.sliderMatrix|first %}
        {% set image = block.image|first %}
    {% endif %}

    {{ image.url }}

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

<p>The code throws this error: Impossible to access an attribute ("url") on a string variable ("hello")</p>

<p><code>{{ image.url }}</code> inside the if statement works fine.</p>

<p><code>{{ image }}</code> outside the if statement works too.</p>

<p>Is there anything I don't know or it's even a bug?</p>

CC BY-SA 3.0
2015-03-17T21:10:51.997Z
The code seems to be alright. Can you detail how your matrix is set up? Maybe a screenshot?
Aaron Berkowitz
<macro><scope>
Problem with scope in macro
# Problem with scope in macro

(Asked by: username_0 on 2015-03-17)

I've written a short macro to get the first image inside a matrix field.
{% macro firstImage(entry) %}

    {% set image = 'hello' %}

    {% if entry.sliderMatrix.total() %}
        {% set block = entry.sliderMatrix|first %}
        {% set image = block.image|first %}
    {% endif %}

    {{ image.url }}

{% endmacro %}

The code throws this error: Impossible to access an attribute ("url") on a string variable ("hello")
{{ image.url }} inside the if statement works fine.
{{ image }} outside the if statement works too.
Is there anything I don't know or it's even a bug?

**Tags:** macro, scope
> **Comments:**
> **username_1**: The code seems to be alright. Can you detail how your matrix is set up? Maybe a screenshot?  

---

## 2 answers

### Answer by username_2 on 2015-03-17. Score: 2 | Accepted answer

Your syntax is close, but not quite right and you're setting a variable as a string and later setting it as an Element Model. I think you're searching for something closer to this:
{% macro firstImage(entry) %}

    {% if entry.sliderMatrix.total() %}
        {% set block = entry.sliderMatrix.first %}
        {% set image = block.image.first %}
    {% endif %}

    {% if image is defined and image %}
        {{ image.url }}
    {% endif %}

{% endmacro %}

> **Comments:**
> **username_3**: This syntax is much better! May I suggest `if image is defined`?  
> **username_2**: You surely may :-)  
> **username_4**: @Christian if that asset field is not marked as required you should also check if `first()` actually returns an image, so use this conditional `{% if image is defined and image %}`.  
> **username_5**: Even if that asset field **is** marked as required you should still check if `first()` actually returns an image. If that required image is deleted after the entry is created you will end up with an entry with no image.  

---

### Answer by username_3 on 2015-03-17. Score: 3

Hard to say for sure, but here's what I suspect... You may have multiple instances of `firstImage` being called from your main template.

For some of those instances, `entry.sliderMatrix.total` is **greater than** zero. For other instances, `entry.sliderMatrix.total` is **equal to** zero. And of course, when `entry.sliderMatrix.total` is equal to zero, your `if` statement will be bypassed.

Realistically, you shouldn't have the `image.url` call outside of your `if` statement. Because any time the `if` statement evaluates to *false*, then the `image` variable won't be what you want it to be. In fact, you'll get that exact error, since `image` will still be set to a string.


---

