I'm sure I'm doing something wrong here, but I'm at a loss as to what. I'm using Craft 3. My travel entry has 7 fields, one of those being a matrix field. My matrix has two blocks, postText and postImage.

Here's the bit of code I'm working with:

{% for block in entry.mainPost.all() %}
  {% if block.type == "postImage" %}
    {% set image = block.image.one() %}
        {% if image %}
            <img src="{{ image.getUrl('summaryImage')}}" alt="">
        {% endif %}
  {% endif %}
{% endfor %}

I have an entry that has two images in the Matrix field. When I load the page, both images load. The documentation states that using .one() "Returns the first matching element". I have to assume that I'm not understanding the ElementCriteriaModel or Assets or the way Matrix works or something.


Yes you're correct, one() will get the first matching element. However, in your code you're not asking for the first image block, but rather the first image from each image block (because each image field can have multiple images attached to it).

The structure is basically something like this:

entry          <- 1. The entry
  mainPost     <- 2. The matrix field
    postImage  <- 3. The matrix field's block
      image    <- 4. The field inside the matrix field's block

We want to get the first result from #3 but you're currently only asking for the first result from #4. (It is probably a good idea to also ask for the first result from #4 as well btw.)

I think something like the following would work in your case:

{% for block in entry.mainPost.type("postImage").limit(1).all() %}
  {% set image = block.image.one() %}
  {% if image %}
    <img src="{{ image.getUrl('summaryImage')}}" alt="">
  {% endif %}
{% endfor %}

UPDATE: looks like you actually need to use limit() instead of one() when querying for the block.

UPDATE 2: tacked on the all() to fix the deprecation!

  • Thanks for the response! I added your code in place of what I had and received the following error message: Impossible to access an attribute ("image") on a string variable ("46"). If I remove .one() from entry.mainPost.type("postImage), my page loads, but without any images... – Shad Apr 10 '18 at 0:36
  • The line number it gives as having the problem is {% set image = block.image.one() %} – Shad Apr 10 '18 at 0:38
  • Oops lol - I'll blame it on how late it is. I updated my post - looks like you'll have to use limit(1) vs one(). I tested it locally on one of my sites and this seems to actually work. :P – Jalen Davenport Apr 10 '18 at 0:45
  • Thanks again! And yes, that's working as expected now. However, as I'm using Craft 3, I'm getting the Deprecation Error "Looping through element queries directly has been deprecated. Use the all() function to fetch the query results before looping over them." – Shad Apr 10 '18 at 0:49
  • Ah yes, so just tack on .all() to the end and you should be good to go! – Jalen Davenport Apr 10 '18 at 0:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.