1

We're trying to filter by categories AND tags in the one form. However can't seem to get things working as we would like.

Essentially, we have a form that pulls in the tags and allows multiple filtering dropdowns. The below is out results page code, which outputs odd results. We need all params to match the entries categories/tags but it just doesn't work as expected. Where are we going wrong?

    {# Get params #}
    {% set mainCategory = craft.app.request.getParam(‘category’) %}
    {% set season = craft.app.request.getParam(‘season’) %}
    {% set age = craft.app.request.getParam(‘ages’) %}

    {# Set arrays #}
    {% set mainCat = mainCategory ? craft.categories.group(‘courseCategories’).slug(mainCategory).all() %}
    {% set seasonCat = season ? craft.tags.group(‘season’).slug(season).all() %}
    {% set ageCat = age ? craft.tags.group(‘ageRange’).slug(age).all() %}

    {# Set relatedTo #}
    {% set categoryParam = mainCat ? {targetElement: [‘and’]|merge(mainCat)} %}
    {% set seasonParam = seasonCat ? {targetElement: [‘and’]|merge(seasonCat)} %}
    {% set ageParam = ageCat ? {targetElement: [‘and’]|merge(ageCat)} %}

    {# Get entries #}
    {% set relationParams = [categoryParam, seasonParam, ageParam]|filter %}
    {% set entries = craft.entries({
        section: ‘courses’,
        relatedTo: relationParams ? [‘and’]|merge(relationParams) : null
    }) %}
1

You are always one level too deep. Craft is able to proceed parameters like

[
    'and',
    ['targetElement' => [1, 2, 3],
    ['targetElement' => ['or', 1, 2, 3],
    ['targetElement' => 1],
    ['targetElement' => ['and', 1, 2, 3]
]

And so on. Yours is

'targetElement' => ['and', [1,2,3]]

I would suggest you to dump your array

<pre>
{{ dump(array) }}
</pre>

To see the result. If you don't care about performance just using .one() instead of all() might solve the problem.

1

So it turns out there were a few things wrong. Firstly my tag slugs were wrong and didn't match in the database (Craft needs to improve how it handles tags...)

Secondly, I had to change my code as Robin suggested to .one() instead of grabbing the full array.

Thirdly, I had to change my targetElement to 'or' for each array merge then 'and' for the final parameter merge. Here is my working code for filtering results based on categories/tags combined:

{% set mainCategory = craft.app.request.getParam('category') %}
{% set season = craft.app.request.getParam('season') %}
{% set age = craft.app.request.getParam('ages') %}

{% set mainCat = mainCategory ? craft.categories.group('courseCategories').slug(mainCategory).one() %}
{% set seasonCat = season ? craft.tags.group('season').slug(season).one() %}
{% set ageCat = age ? craft.tags.group('ageRange').slug(age).one() %}

{% set categoryParam = mainCat ? {targetElement: ['or']|merge(mainCat)} %}
{% set seasonParam = seasonCat ? {targetElement: ['or']|merge(seasonCat)} %}
{% set ageParam = ageCat ? {targetElement: ['or']|merge(ageCat)} %}

{% set relationParams = [categoryParam, seasonParam, ageParam]|filter %}
{% set entries = craft.entries({
    section: 'courses',
    relatedTo: relationParams ? ['and']|merge(relationParams) : null
}) %}
  • Feel free to create a feature request but I think Craft does nothing wrong here. In fact you don't need the or param at all so you could avoid all those array merges – Robin Schambach Oct 7 '18 at 11:34

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.