<p>After some help from @RobinSchambach on the Craft Slack and a bit of trial and error I got to this, truncated for brevity.</p>

<pre><code>{# clear everything #}
    {% set colourQuery = '' %}
    {% set sizeQuery = '' %}

    {# get all the search query parameters #}
    {% set colour = craft.request.getParam('colour') %}
    {% set size = craft.request.getParam('size') %}


    {% set colourQuery = colour | join(',') %}
    {% set sizeQuery = size | join(',') %}


    {# colour #}
    {% set colourParams = ['or'] %}
    {% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# size #}
    {% set sizeParams = ['or'] %}
    {% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
    {% endfor %}




    {# build criteria #}
    {% set relatedParams = ['and'] %}
    {% if colourQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : colourQuery}]) %}
    {% endif %}

    {% if sizeQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : sizeQuery}]) %}
    {% endif %}
</code></pre>

<p>The key difference is that I'm using the Category IDs rather than their slugs. I'm then passing them as comma delimited strings into the array to build up the criteria.</p>

<p>I'm working on refining this a bit more but it's now working as expected.</p>

CC BY-SA 4.0
2018-07-16T19:42:09.030Z
2018-07-16T19:42:09.030Z
foamcow
<p>I'm trying to figure out how to set up my relatedTo paramaters to do a category search. Normally it's not a problem but in this case I need something more complex than normal.</p>

<p>I have multiple category groups. Within each group I need to use an "or" condition. So entries are returned if they match any categories in that group. </p>

<p>But across the different groups I need to apply an "and" condition.</p>

<p>i.e. Group 1 is "colours", Group 2 is "size"</p>

<p>So if someone selects:
Group 1: black, blue
Group 2: small</p>

<p>I want to return any entries that are (black OR blue) AND (small)</p>

<p>Setting the 'or' condition within a group is no problem but I'm stumped on how I can merge the different sets of parameters together to get the desired results.</p>

<p>This is a truncated version of what I have so far, just showing 2 of my groups.</p>

<pre><code>{# clear everything #}
{% set colourQuery = '' %}
{% set sizeQuery = '' %}

{# get all the search query parameters #}
{% set colour = craft.request.getParam('colour') %}
{% set size = craft.request.getParam('size') %}

{% set colourQuery = colour | join(',') %}
{% set sizeQuery = size | join(',') %}

{# colour #}
{% set colourParams = ['or'] %}
{% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
{% endfor %}

{# size #}
{% set sizeParams = ['or'] %}
{% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
{% endfor %}
</code></pre>

<p>Then I build the criteria... I'm sure this is where I'm going wrong</p>

<pre><code>{# build criteria #}
{% set relatedParams = [] %}

{% set relatedParams = relatedParams | merge(colourParams) %}
{% set relatedParams = relatedParams | merge(sizeParams) %}
</code></pre>

<p>I've also tried</p>

<pre><code>{# build criteria #}
{% set relatedParams = [
        ['and', colourParams],
        ['and', sizeParams],
    ] 
%}
</code></pre>

<p>I'm using <code>relatedParams</code> like so:</p>

<pre><code>{% set products = craft.commerce.products('products').relatedTo(relatedParams).order(sortString).limit(numPerPage) %}
</code></pre>

<p>So, my question is how should I join those different paramater arrays in order to get what I need?</p>

<categories><relatedto>
Returning entries based on Relationships across different category groups using 'and'
# Returning entries based on Relationships across different category groups using 'and'

(Asked by: username_0 on 2018-07-16)

I'm trying to figure out how to set up my relatedTo paramaters to do a category search. Normally it's not a problem but in this case I need something more complex than normal.
I have multiple category groups. Within each group I need to use an "or" condition. So entries are returned if they match any categories in that group. 
But across the different groups I need to apply an "and" condition.
i.e. Group 1 is "colours", Group 2 is "size"
So if someone selects:
Group 1: black, blue
Group 2: small
I want to return any entries that are (black OR blue) AND (small)
Setting the 'or' condition within a group is no problem but I'm stumped on how I can merge the different sets of parameters together to get the desired results.
This is a truncated version of what I have so far, just showing 2 of my groups.
{# clear everything #}
{% set colourQuery = '' %}
{% set sizeQuery = '' %}

{# get all the search query parameters #}
{% set colour = craft.request.getParam('colour') %}
{% set size = craft.request.getParam('size') %}

{% set colourQuery = colour | join(',') %}
{% set sizeQuery = size | join(',') %}

{# colour #}
{% set colourParams = ['or'] %}
{% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
{% endfor %}

{# size #}
{% set sizeParams = ['or'] %}
{% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
{% for cat in cats %}
    {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
{% endfor %}

Then I build the criteria... I'm sure this is where I'm going wrong
{# build criteria #}
{% set relatedParams = [] %}

{% set relatedParams = relatedParams | merge(colourParams) %}
{% set relatedParams = relatedParams | merge(sizeParams) %}

I've also tried
{# build criteria #}
{% set relatedParams = [
        ['and', colourParams],
        ['and', sizeParams],
    ] 
%}

I'm using relatedParams like so:
{% set products = craft.commerce.products('products').relatedTo(relatedParams).order(sortString).limit(numPerPage) %}

So, my question is how should I join those different paramater arrays in order to get what I need?

**Tags:** categories, relatedto


---

## 1 answers

### Answer by username_0 on 2018-07-16. Score: 2

After some help from @RobinSchambach on the Craft Slack and a bit of trial and error I got to this, truncated for brevity.
{# clear everything #}
    {% set colourQuery = '' %}
    {% set sizeQuery = '' %}

    {# get all the search query parameters #}
    {% set colour = craft.request.getParam('colour') %}
    {% set size = craft.request.getParam('size') %}


    {% set colourQuery = colour | join(',') %}
    {% set sizeQuery = size | join(',') %}


    {# colour #}
    {% set colourParams = ['or'] %}
    {% set cats = craft.categories.group('colour').slug( colourQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set colourParams = colourParams | merge([{ targetElement: cat }]) %}
    {% endfor %}

    {# size #}
    {% set sizeParams = ['or'] %}
    {% set cats = craft.categories.group('size').slug( sizeQuery | split(',') ).find() %}
    {% for cat in cats %}
        {% set sizeParams = sizeParams | merge([{ targetElement: cat }]) %}
    {% endfor %}




    {# build criteria #}
    {% set relatedParams = ['and'] %}
    {% if colourQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : colourQuery}]) %}
    {% endif %}

    {% if sizeQuery != '' %}
        {% set relatedParams = relatedParams | merge([{element : sizeQuery}]) %}
    {% endif %}

The key difference is that I'm using the Category IDs rather than their slugs. I'm then passing them as comma delimited strings into the array to build up the criteria.
I'm working on refining this a bit more but it's now working as expected.


---

