<p>I've looked at it further and arrived at a solution.</p>

<p>The <code>relations</code> array needed to be in the form <code>['and', {element: [22, 33]}, {element: [42, 43, 44]}, {element: 65}]</code>.</p>

<p>So that could be done using the following:</p>

<pre><code>{% set relations = relations|merge([{element:filterValues}]) %}
</code></pre>

CC BY-SA 3.0
2017-11-29T12:29:40.413Z
2017-11-29T12:39:36.100Z
2017-11-29T12:39:36.100Z
Alex H
<p>I'm trying to set up a filtering system similar to the <a href="http://www.asos.com/men/shoes-boots-trainers/cat/?cid=4209&amp;refine=attribute_1027:7504%7Cbase_colour:11,16,33&amp;currentpricerange=0-290&amp;pgesize=36" rel="nofollow noreferrer">one found on the product pages on asos.com</a>. That system has different category groups of filters, where selecting multiple filters inside a particular category group widens the results list (OR / conjuction), whereas filters across category groups narrow the results list (AND / disjunction).</p>

<p>I'm trying to replicate this behaviour in Craft, but I'm struggling to combine AND and OR relations. I currently do the following to build up a list of filters across category groups from a comma separated query string in the form <code>?regions=22,33&amp;teams=65&amp;sectors=42,43,44</code>:</p>

<pre><code>{% set categoryGroups = ['regions', 'teams', 'sectors', 'topics'] %}
{% set relations = ['and'] %}
{% for group in categoryGroups %}
  {% set filterValueString = craft.request.getParam(group) %}
  {% if filterValueString != '' %}
    {% set filterValues = filterValueString|split(',') %}
    {% set relations = relations|merge(filterValues) %}
  {% endif %}
{% endfor %}

{% if relations | length &gt; 1 %}
  {% set params = params | merge({ relatedTo: relations }) %}
{% endif %}

{% set results = craft.entries(params) %}
</code></pre>

<p>This results in a <code>relations</code> array which looks like <code>['and', 22, 33, 42, 43, 44, 65]</code>, and creates a system where adding a filter to an already filtered category group restricts the result set further, instead of widening it to encompass the new filter. I thought perhaps that I could construct <code>relations</code> to look like <code>['and', [22, 33], [42, 43, 44], 65]</code>, and the inner arrays (category groups) would default to an OR (as it would when passing a standard array of element IDs into <code>relatedTo</code>), with the outer relation providing the AND, but this doesn't appear to work.</p>

<p>Is there anyway to get the behaviour I'm looking for?</p>

CC BY-SA 3.0
2017-11-29T12:19:45.903Z
Yes but I'm not sure if twig is suited for that. My hint would be: create a plugin variable and do it with php, you can create a query from your `ElementCriteriaModel` and include your conditions freely like you want
Robin Schambach
CC BY-SA 3.0
2017-11-29T12:30:05.630Z
Agreed, this was probably a little much for twig but I got to a solution!
Alex H
<categories><relations><logic>
Building a filtering system using both OR and AND relations
# Building a filtering system using both OR and AND relations

(Asked by: username_0 on 2017-11-29)

I'm trying to set up a filtering system similar to the one found on the product pages on asos.com. That system has different category groups of filters, where selecting multiple filters inside a particular category group widens the results list (OR / conjuction), whereas filters across category groups narrow the results list (AND / disjunction).
I'm trying to replicate this behaviour in Craft, but I'm struggling to combine AND and OR relations. I currently do the following to build up a list of filters across category groups from a comma separated query string in the form ?regions=22,33&teams=65&sectors=42,43,44:
{% set categoryGroups = ['regions', 'teams', 'sectors', 'topics'] %}
{% set relations = ['and'] %}
{% for group in categoryGroups %}
  {% set filterValueString = craft.request.getParam(group) %}
  {% if filterValueString != '' %}
    {% set filterValues = filterValueString|split(',') %}
    {% set relations = relations|merge(filterValues) %}
  {% endif %}
{% endfor %}

{% if relations | length > 1 %}
  {% set params = params | merge({ relatedTo: relations }) %}
{% endif %}

{% set results = craft.entries(params) %}

This results in a relations array which looks like ['and', 22, 33, 42, 43, 44, 65], and creates a system where adding a filter to an already filtered category group restricts the result set further, instead of widening it to encompass the new filter. I thought perhaps that I could construct relations to look like ['and', [22, 33], [42, 43, 44], 65], and the inner arrays (category groups) would default to an OR (as it would when passing a standard array of element IDs into relatedTo), with the outer relation providing the AND, but this doesn't appear to work.
Is there anyway to get the behaviour I'm looking for?

**Tags:** categories, relations, logic
> **Comments:**
> **username_1**: Yes but I'm not sure if twig is suited for that. My hint would be: create a plugin variable and do it with php, you can create a query from your `ElementCriteriaModel` and include your conditions freely like you want  
> **username_0**: Agreed, this was probably a little much for twig but I got to a solution!  

---

## 1 answers

### Answer by username_0 on 2017-11-29. Score: 2

I've looked at it further and arrived at a solution.
The relations array needed to be in the form ['and', {element: [22, 33]}, {element: [42, 43, 44]}, {element: 65}].
So that could be done using the following:
{% set relations = relations|merge([{element:filterValues}]) %}


---

