3

I have a Matrix field that has an Entries field. I want to get those entries, in the selected order, removing entries that don’t have an image asset assigned to the pageImage field.

Attempt 1
Gets correct entries but doesn’t maintain the selection order.

block.entries.relatedTo('and', {
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
})

Attempt 2
Same result as above. Correct entries but wrong order.

craft.entries.relatedTo('and', {
  sourceElement: block
}, {
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
})

Setting the field value in the first statement results in an empty result set.

Attempt 3
Seems to work but generates extra queries.

{% set ids = block.entries.ids() %}
{% set entries = craft.entries.id(ids).fixedOrder(ids).relatedTo({
  targetElement: craft.assets.kind('image'),
  field: 'pageImage'
}) %}
3

While you said that Attempt 1 was giving you the correct entries, just in the wrong order, if you have two blocks, you will probably find that you’re getting all blocks’ related entries each time. Because when you set that relatedTo param on block.entries, you’re actually overriding the existing relatedTo param that the Entries field type set, which limits entries to just those that are related to the current block. So with a little more testing you’ll find that’s more than just an ordering problem.

Attempt 2 is the right way to go - finding entries that are explicitly related to both the current block and some number of assets. If you want those entries to show up in the order they were related within the current block, you just need to set the order param. In this case you’ll want to set that to sources1.sortOrder, as sources1 is the alias that the craft_relations will get when it’s joined into the query to aid in a sourceElement relation param for the first time.

craft.entries({
    relatedTo: [
        'and',
        { sourceElement: block },
        { targetElement: craft.assets.kind('image'), field: 'pageImage' }
    ],
    order: 'sources1.sortOrder'
})

One thing I would recommend is, if you are going to be running this same query on multiple Matrix blocks on the same page, you should define that craft.assets ElementCriteriaModel outside of the main for-loop. That will save Craft a DB query for each block.

{% set allImages = craft.assets.kind('image').limit(null) %}

{% for block in entry.myMatrixField %}

    {% set entries = craft.entries({
        relatedTo: [
            'and',
            { sourceElement: block },
            { targetElement: allImages, field: 'pageImage' }
        ],
        order: 'sources1.sortOrder'
    }) %}

    ...

{% endfor %}
| improve this answer | |

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.