<p>You can write a custom plugin and make use of Craft's <a href="http://buildwithcraft.com/classreference/services/ElementsService#buildElementsQuery-detail" rel="nofollow"><code>buildElementsQuery</code></a>, to be able to add <a href="http://buildwithcraft.com/docs/plugins/database" rel="nofollow">custom query statements</a> to your ElementCriteriaModel.</p>

<p>Give your plugin a <a href="http://buildwithcraft.com/docs/plugins/variables" rel="nofollow">Template Variable</a> <code>addVideoBlockCriteria</code> and with some lines of plugin code you will be able to do something like this from your template:</p>

<pre><code>{% set criteria = craft.entries.section('blog').order('title asc') %}
{% set entries = craft.businesslogic.addVideoBlockCriteria(criteria) %}

{% for entry in entries %}
    ...
{% endfor %}
</code></pre>

<p>Make your Template Variable pass the criteria to a plugin service, run them through <code>buildElementsQuery</code>, and you can now modify the query with some <a href="http://buildwithcraft.com/classreference/etc/db/DbCommand" rel="nofollow">DbCommands</a>.</p>

<pre><code>public function addVideoBlockCriteria(ElementCriteriaModel $criteria)
{
    $query = craft()-&gt;elements-&gt;buildElementsQuery($criteria);

    $query-&gt;andWhere('matrixcontent_article.field_video_videoUrl is not null');

    $query-&gt;join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
    $query-&gt;join('matrixcontent_article matrixcontent_article', 'matrixcontent_article.elementId = matrixblocks.id');

    $results = $query-&gt;queryAll();

    return EntryModel::populateModels($results);
}
</code></pre>

<p>Use <code>join</code> to bring in the "matrixblocks" table and also your Matrix field's content table "matrixcontent_<em>mymatrixfield</em>". And add the conditions with <code>andWhere</code>;  the Matrix field's fields column names follow a scheme "field_<em>myMatrixBlockType</em>_<em>myFieldInMatrixBlock</em>".</p>

CC BY-SA 3.0
2015-06-14T14:24:20.630Z
2015-06-14T14:24:20.630Z
carlcs
<blockquote>
  <p>Idea 2 [...] Add a light switch field to the channel called "hasVideo". Update this field programmatically using the onSave event and a plugin. Then I can select all entries if hasVideo is true.</p>
</blockquote>

<p>If you're going to write your own plugin I would encourage you to implement carlcs' solution, which is a solid one, rather than going for what is basically a hack.</p>

<p>However, if you do decide to use <a href="https://github.com/low/lowblocks" rel="nofollow">Low Blocks</a> instead and do the heavy lifting in your template, here's how that could work:</p>

<pre><code>{# Get blocks, using the field ID, filtering by block type #}
{% set blocks = craft.lowblocks.blocks.fieldId(22).type('video') %}

{# Get entry IDs #}
{% set entryIds = [] %}
{% for block in blocks %}
    {% set entryId = block.owner.id %}
    {% set entryIds = entryIds|merge([entryId]) %}
{% endfor %}

{# Get entries #}
{% set entries = craft.entries({ id : entryIds }) %}
</code></pre>

<p>Not super elegant, but it should work. Personally I'm a big fan of keeping templates as logic-free and simple as possible, so I'd probably go for carlcs' solution, myself.</p>

<p><em>Note: Be sure to switch out the number <code>22</code> in my example Twig for the actual ID of your Matrix field.</em></p>

CC BY-SA 3.0
2015-06-15T11:37:27.603Z
I will look into carlcs's answer but I don't see option #2 as a hack. Isn't it just denormalisation?
Jamie Pittock
CC BY-SA 3.0
2015-06-15T11:54:50.903Z
Sure, you can consider it that, and it's probably a totally viable solution. It's a matter of perspective, of course – the reason I'd personally consider it a hack is that you'll end up with this odd relationship between a Matrix field and another, separate Lightswitch field. The latter won't be something your editor(s) should (or can) interact with, so it should probably be hidden using CSS so it won't confuse them. It adds up to a hack for me, though being a hack doesn't necessarily make it a "bad" way to accomplish your goal. I just think carlcs' solution would be more robust and in line.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2015-06-14T18:54:40.893Z
2015-06-14T18:54:40.893Z
Mats Mikkel Rummelhoff
<p>Say I have a channel with a matrix field which has two block types - text and video. Is there any way to select all entries in that channel that have a video block?</p>

<p>Idea 1</p>

<p>Use the Low Blocks plugin to query all video block types, then get their owner IDs, then use those to grab the entries.</p>

<p>Idea 2</p>

<p>Add a light switch field to the channel called "hasVideo". Update this field programmatically using the onSave event and a plugin. Then I can select all entries if hasVideo is true.</p>

<p>Is there a better way I'm missing?</p>

<entries><matrix><block-types>
How do I select entries that have a particular block type?
# How do I select entries that have a particular block type?

(Asked by: username_0 on 2015-06-13)

Say I have a channel with a matrix field which has two block types - text and video. Is there any way to select all entries in that channel that have a video block?

Idea 1

Use the Low Blocks plugin to query all video block types, then get their owner IDs, then use those to grab the entries.

Idea 2

Add a light switch field to the channel called "hasVideo". Update this field programmatically using the onSave event and a plugin. Then I can select all entries if hasVideo is true.

Is there a better way I'm missing?

**Tags:** entries, matrix, block-types

---

## 2 answers

### Answer by username_1 on 2015-06-14. Score: 2

You can write a custom plugin and make use of Craft's buildElementsQuery, to be able to add custom query statements to your ElementCriteriaModel.
Give your plugin a Template Variable addVideoBlockCriteria and with some lines of plugin code you will be able to do something like this from your template:
{% set criteria = craft.entries.section('blog').order('title asc') %}
{% set entries = craft.businesslogic.addVideoBlockCriteria(criteria) %}

{% for entry in entries %}
    ...
{% endfor %}

Make your Template Variable pass the criteria to a plugin service, run them through buildElementsQuery, and you can now modify the query with some DbCommands.
public function addVideoBlockCriteria(ElementCriteriaModel $criteria)
{
    $query = craft()->elements->buildElementsQuery($criteria);

    $query->andWhere('matrixcontent_article.field_video_videoUrl is not null');

    $query->join('matrixblocks matrixblocks', 'matrixblocks.ownerId = entries.id');
    $query->join('matrixcontent_article matrixcontent_article', 'matrixcontent_article.elementId = matrixblocks.id');

    $results = $query->queryAll();

    return EntryModel::populateModels($results);
}

Use join to bring in the "matrixblocks" table and also your Matrix field's content table "matrixcontent_mymatrixfield". And add the conditions with andWhere;  the Matrix field's fields column names follow a scheme "field_myMatrixBlockType_myFieldInMatrixBlock".


---

### Answer by username_2 on 2015-06-14. Score: 1

Idea 2 [...] Add a light switch field to the channel called "hasVideo". Update this field programmatically using the onSave event and a plugin. Then I can select all entries if hasVideo is true.

If you're going to write your own plugin I would encourage you to implement carlcs' solution, which is a solid one, rather than going for what is basically a hack.
However, if you do decide to use Low Blocks instead and do the heavy lifting in your template, here's how that could work:
{# Get blocks, using the field ID, filtering by block type #}
{% set blocks = craft.lowblocks.blocks.fieldId(22).type('video') %}

{# Get entry IDs #}
{% set entryIds = [] %}
{% for block in blocks %}
    {% set entryId = block.owner.id %}
    {% set entryIds = entryIds|merge([entryId]) %}
{% endfor %}

{# Get entries #}
{% set entries = craft.entries({ id : entryIds }) %}

Not super elegant, but it should work. Personally I'm a big fan of keeping templates as logic-free and simple as possible, so I'd probably go for carlcs' solution, myself.
Note: Be sure to switch out the number 22 in my example Twig for the actual ID of your Matrix field.

> **Comments:**
> **username_0**: I will look into carlcs's answer but I don't see option #2 as a hack. Isn't it just denormalisation?  
> **username_2**: Sure, you can consider it that, and it's probably a totally viable solution. It's a matter of perspective, of course – the reason I'd personally consider it a hack is that you'll end up with this odd relationship between a Matrix field and another, separate Lightswitch field. The latter won't be something your editor(s) should (or can) interact with, so it should probably be hidden using CSS so it won't confuse them. It adds up to a hack for me, though being a hack doesn't necessarily make it a "bad" way to accomplish your goal. I just think carlcs' solution would be more robust and in line.  

---

