In Craft, is there a field that allows the user to create a custom query in the back-end?

Something similar to the filters in Wordpress' query loop block? https://wordpress.org/support/article/query-loop-block/

Drupal Views is probably another good example.

For example - In Matrix, a user could select a 'loop' block which output's cards for entries. They could create a query such as Articles from 6 months ago that are tagged X.

I know it's possible via Relations but looking for a more dynamic solution.



There's no pre-built field in the core for this, and I don't know of any plugin that provides something like this. However, you can build your own pretty easily! For example, let's say you want a matrix block that will automatically find entries based on filters selected in the matrix block. You can solve that by providing fields in the matrix block and building a custom query based on those. A simple example could have the following fields:

  • Entry type (entry_types) – A Checkboxes field with options for all entry types that can be displayed.
  • Categories (categories) – A Categories field relating to a category that is also available on some (or all) of your public entry types.
  • Limit (limit) – A Number field to limit the amount of entries that are displayed (set to allow only integers, i.e. no decimal places).

Given those fields (field handles in parenthesis), here's how you can parse those fields and create an entry query based on the selected values in your block template:

{# The `block` variable is the matrix block. #}

{# Create a new entry query. #}
{% set entriesQuery = craft.entries().orderBy('postdate DESC') %}

{# Set the allowed entry types, if any. #}
{% set types = block.types ?? [] %}
{% if types is instance of('craft\\fields\\data\\MultiOptionsFieldData') %}
    {# This assumes your `types` field is a checkboxes field with entry type handles as values. #}
    {% set types = types|column('value') %}
{% endif %}
{% if types %}
    {% do entriesQuery.type(types) %}
{% endif %}

{# Set the allowed categories #}
{% set allowedCategories = block.categories.ids() %}
{% if allowedCategories %}
    {% do entriesQuery.relatedTo({
        targetElement: allowedCategories
    }) %}
{% endif %}

{# Set the limit (with a sensible default). #}
{% set limit = block.limit ?? 10 %}
{% do entriesQuery.limit(limit) %}

Once you have added all selected parameters / filters to the query, you can execute it and display the results however you want:

{% set results = entriesQuery.all() %}

<ul class="automatic-lister">
    {% for result in results %}
        <li class="automatic-lister__item">
            <a href="{{ result.getUrl() }}" class="automatic-lister__link">
                {{- result.title -}}
    {% endfor %}

Now you can extend the block however you like, adding more parameters depending on the fields you want to filter by. For example, you could add a text field to find matching entries, a tags field to filter entries by tag, an option to change the sort order … possibilities are endless!

  • 1
    Amazing..! I knew it'd be possible to do it this way but didn't realise it could be so straightforward. Thank you so much - look forward to putting this to use!
    – Aron15
    Oct 21 '21 at 14:48

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.