3

Let’s say I have a site with two sections: Things and Colors.

Things has a Matrix field (thingsBlocks) with a Sizes block type. That Sizes block type has a checkboxes field (sizes) with values that will be important again in a moment.

The Colors section has an entries field (thingsEntries) for relationships to Things.

My goal is to query Colors entries related to Things that have Sizes blocks with specific size values checked, and I’d like this to be an element query I can use with pagination.

The following pseudo-code is pure fantasy and does not work:

{% set colorsWithSizedThings = craft.entries()
  .section('colors')
  .thingsEntries(['thingsBlocks' => ['sizes' => ['sizeA', 'sizeD']])
  .all()

1 Answer 1

1

You can do it, but you’ll need to break it into a few steps:

  1. Get the Matrix blocks having the desired checked size values.
  2. Get the IDs of the Things entries that own those Matrix blocks.
  3. Get the Colors entries related to those Things entries by their IDs.

For context, we can quickly dump out our Things and their sizes along with our Colors and their related Things:

{# ------------------------------------------------------ #}
{# Establishing Context                                   #}
{# ------------------------------------------------------ #}

{% set things = craft.entries().section('things').all() %}
{% set colors = craft.entries().section('colors').all() %}

<h2>Things</h2>
<ul>
  {% for thing in things %}
    <li>
      {{ thing.title }}<br>
      {% for size in thing.thingsBlocks.type('sizes').one().sizes %}
        <code>✓ {{ size }}</code>
        {% if not loop.last %}<br>{% endif %}
      {% endfor %}
    </li>
  {% endfor %}
</ul>

<h2>Colors</h2>
<ul>
  {% for color in colors %}
    <li>
      {{ color.title }}<br>
      {% for thing in color.thingsEntries.all() %}
        <code>{{ thing.title }}</code>
        {% if not loop.last %}<br>{% endif %}
      {% endfor %}
    </li>
  {% endfor %}
</ul>

And the query might look something like this:

{# ------------------------------------------------------ #}
{# The Part with the Answer                               #}
{# ------------------------------------------------------ #}

<h2>Colors with Specifically-Sized Things</h2>

{# Specify the checkbox size values we want #}
{% set targetSizes = ['sizeA', 'sizeD'] %}

<p>Colors entries related to Things with {{ targetSizes|join(' or ') }}.</p>

{# 1+2. Get IDs of entries owning the Matrix blocks with our desired sizes #}
{% set targetThingsEntryIds = craft.matrixBlocks()
  .field('thingsBlocks')
  .type('sizes')
  .sizes(targetSizes)
  .select('ownerId')
  .column() %}

{# 3. Query Colors entries with relationships to the target Things entries #}
{% set colorsWithSizedThings = craft.entries()
  .section('colors')
  .thingsEntries(targetThingsEntryIds)
  .all() %}

{# Tersely output list of resulting entry titles #}
{{ ul(colorsWithSizedThings|map((entry) => "#{entry.title}")) }}

colorsWithSizedThings will work with pagination like any other element query.

That .sizes(targetSizes) part will query either of the provided values (or). See the Checkboxes Fields page for other query options including treating the value array as an and—meaning all provided options must be checked rather than any of them.


Edit 11/30/21

Andrew demonstrated how to accomplish this using a custom behavior:
Searching Craft CMS Matrix Blocks

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.