<p>After a lot of back and forth and reading various posts on this I thought I would submit my answer. There maybe better ways of doing what I ended up doing but hopefully this will provide a start for someone wanting to do the same.</p>

<p>First here are a few posts and questions that helped:</p>

<ul>
<li><p><a href="https://craftcms.stackexchange.com/questions/8614/find-entries-with-multiple-categories-with-an-and-or-twist">Find entries with multiple categories with an and/or twist</a></p></li>
<li><p><a href="https://craftcms.stackexchange.com/questions/4560/how-can-i-create-an-elementcriteriamodel-with-and-and-or">How can I create an ElementCriteriaModel with &#39;and&#39; and &#39;or&#39;</a></p></li>
<li><p><a href="http://webstoemp.com/blog/combined-searches-and-filters-craft-cms" rel="nofollow noreferrer">Combined searches and filters using Craft</a></p></li>
</ul>

<p><strong>My Solution</strong></p>

<p>First I created a search form that had the checkboxes for the search, each checkbox name when posted would form the get variable for the filter. A check is done to see if there are categories, if there are then I loop through and add them. There is also a check done to see if you are on the filter results page, if you are then set the relevant checkboxes to checked on the form.</p>

<p><strong>The Search Form Code</strong></p>

<pre><code>&lt;form action="{{ url('homes-for-sale/filter') }}" method="get"&gt;

  {# check if there are any park categories if there are then show them as checkboxes #}

  {% if parkCategories|length %}

    {% for category in parkCategories %}
      {% set loopIndex = 'park' ~ loop.index %}
      &lt;label class="checkbox-inline"&gt;

        {# if you are on the filter results page then set the results to checked #}

        {% if template is defined and template == 'filter' %}
          &lt;input type="checkbox" name="{{ loopIndex }}" value="{{ category.slug }}"{% if category.slug == park1 or category.slug == park2 or category.slug == park3 or category.slug == park4 or category.slug == park5 %} checked{% endif %}&gt;
        {% else %}
          &lt;input type="checkbox" name="{{ loopIndex }}" value="{{ category.slug }}"&gt;
        {% endif %}
        {{ category.navTitle }}
      &lt;/label&gt;
    {% endfor %}
  {% endif %}

  {# check if there are any price categories if there are then show them as checkboxes #}

  {% if priceCategories|length %}
    {% for category in priceCategories %}
      {% set loopIndex = 'price' ~ loop.index %}
      &lt;label class="checkbox-inline"&gt;

        {# if you are on the filter results page then set the results to checked #}

        {% if template is defined and template == 'filter' %}
          &lt;input type="checkbox" name="{{ loopIndex }}" value="{{ category.slug }}"{% if category.slug == price1 or category.slug == price2 or category.slug == price3 or category.slug == price4 or category.slug == price5 or category.slug == price6 %} checked{% endif %}&gt;
        {% else %}
          &lt;input type="checkbox" name="{{ loopIndex }}" value="{{ category.slug }}"&gt;
        {% endif %}
        {{ category.title }}
      &lt;/label&gt;
    {% endfor %}
  {% endif %}

  &lt;button type="submit"&gt;Submit&lt;/button&gt;

&lt;/form&gt;
</code></pre>

<p><strong>The Filter Results Page</strong></p>

<p>On the results page you need to check which filter variables have been set via the get request and then display the appropriate related entries.</p>

<pre><code>{# set park search parameters #}
{% set park1 = craft.request.getParam('park1') %}
{% set park2 = craft.request.getParam('park2') %}
{% set park3 = craft.request.getParam('park3') %}
{% set park4 = craft.request.getParam('park4') %}
{% set park5 = craft.request.getParam('park5') %}

{# set price search parameters #}
{% set price1 = craft.request.getParam('price1') %}
{% set price2 = craft.request.getParam('price2') %}
{% set price3 = craft.request.getParam('price3') %}
{% set price4 = craft.request.getParam('price4') %}
{% set price5 = craft.request.getParam('price5') %}
{% set price6 = craft.request.getParam('price6') %}

{# set park category model if it is in the search query #}
{% set parkCategory1 = park1|length ? craft.categories.slug(park1).first().id %}
{% set parkCategory2 = park2|length ? craft.categories.slug(park2).first().id %}
{% set parkCategory3 = park3|length ? craft.categories.slug(park3).first().id %}
{% set parkCategory4 = park4|length ? craft.categories.slug(park4).first().id %}
{% set parkCategory5 = park5|length ? craft.categories.slug(park5).first().id %}

{# create an array of park categories #}
{% set parks = [
  parkCategory1,
  parkCategory2,
  parkCategory3,
  parkCategory4,
  parkCategory5,
] %}

{# create a park array and trim blank strings #}
{% set trimParks = [] %}

{% for park in parks %}
  {% if park|length %}
    {% set trimParks = trimParks|merge({ (loop.index0): park}) %}
  {% endif %}
{% endfor %}

{# set price category model if it is in the search query #}
{% set priceCategory1 = price1|length ? craft.categories.slug(price1).first().id %}
{% set priceCategory2 = price2|length ? craft.categories.slug(price2).first().id %}
{% set priceCategory3 = price3|length ? craft.categories.slug(price3).first().id %}
{% set priceCategory4 = price4|length ? craft.categories.slug(price4).first().id %}
{% set priceCategory5 = price5|length ? craft.categories.slug(price5).first().id %}
{% set priceCategory6 = price6|length ? craft.categories.slug(price6).first().id %}

{# create an array of price categories #}
{% set prices = [
  priceCategory1,
  priceCategory2,
  priceCategory3,
  priceCategory4,
  priceCategory5,
  priceCategory6,
] %}

{# create a price array and trim blank strings #}
{% set trimPrices = [] %}

{% for price in prices %}
  {% if price|length %}
    {% set trimPrices = trimPrices|merge({ (loop.index0): price}) %}
  {% endif %}
{% endfor %}

{% if trimParks|length and trimPrices|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('and',
    {targetElement:parks},
    {targetElement:prices}
  ) %}
{% endif %}

{% if trimParks|length and not trimPrices|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('or',
    {targetElement:parks}
  ) %}
{% endif %}

{% if trimPrices|length and not trimParks|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('or',
    {targetElement:prices}
  ) %}
{% endif %}

&lt;h1&gt;Filter Results&lt;/h1&gt;

{% if entries|length %}
    &lt;p&gt;{{ entries|length }} results:&lt;/p&gt;
    &lt;ul&gt;
        {% for entry in entries %}
          {% set park = entry.park.first() %}
          {% set price = entry.parkPriceCategory.first() %}
          &lt;li&gt;&lt;a href="{{ entry.url }}"&gt;{{ entry.title }} :: &lt;b&gt;{{ park }}&lt;/b&gt; :: &lt;b&gt;{{ price }}&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
{% else %}
    &lt;p&gt;Your search didn't return any results.&lt;/p&gt;
{% endif %}
</code></pre>

CC BY-SA 3.0
2016-03-04T08:16:47.873Z
2016-03-04T11:05:26.967Z
2017-04-13T12:51:00.160Z
Gareth
<p>This question is very similar to the question posted <a href="https://craftcms.stackexchange.com/questions/9081/how-to-filter-entries-by-clicking-multiple-categories-on-front-end">here</a> I have asked in the comments but my requirements are slightly different. I am trying to filter search results by categories in more than one category group and use both an exclusive search (category AND category) and a non exclusive search (category OR category).</p>

<p>My use case is this: the parks category wants to filter using the OR filter so Park A OR Park B and so does the price filter so Price A OR Price B but when they are combined Park A AND Price B only show parks in the Price A category.</p>

<categories><search><filter>
How to filter entries in multiple category groups by selecting multiple categories
# How to filter entries in multiple category groups by selecting multiple categories

(Asked by: username_0 on 2016-02-10)

This question is very similar to the question posted [here](https://craftcms.stackexchange.com/questions/9081/how-to-filter-entries-by-clicking-multiple-categories-on-front-end) I have asked in the comments but my requirements are slightly different. I am trying to filter search results by categories in more than one category group and use both an exclusive search (category AND category) and a non exclusive search (category OR category).

My use case is this: the parks category wants to filter using the OR filter so Park A OR Park B and so does the price filter so Price A OR Price B but when they are combined Park A AND Price B only show parks in the Price A category.

**Tags:** categories, search, filter

---

## 1 answers

### Answer by username_0 on 2016-03-04. Score: 2 | Accepted answer

After a lot of back and forth and reading various posts on this I thought I would submit my answer. There maybe better ways of doing what I ended up doing but hopefully this will provide a start for someone wanting to do the same.
First here are a few posts and questions that helped:

Find entries with multiple categories with an and/or twist
How can I create an ElementCriteriaModel with 'and' and 'or'
Combined searches and filters using Craft

My Solution
First I created a search form that had the checkboxes for the search, each checkbox name when posted would form the get variable for the filter. A check is done to see if there are categories, if there are then I loop through and add them. There is also a check done to see if you are on the filter results page, if you are then set the relevant checkboxes to checked on the form.
The Search Form Code


  {# check if there are any park categories if there are then show them as checkboxes #}

  {% if parkCategories|length %}

    {% for category in parkCategories %}
      {% set loopIndex = 'park' ~ loop.index %}
      

        {# if you are on the filter results page then set the results to checked #}

        {% if template is defined and template == 'filter' %}
          
        {% else %}
          
        {% endif %}
        {{ category.navTitle }}
      
    {% endfor %}
  {% endif %}

  {# check if there are any price categories if there are then show them as checkboxes #}

  {% if priceCategories|length %}
    {% for category in priceCategories %}
      {% set loopIndex = 'price' ~ loop.index %}
      

        {# if you are on the filter results page then set the results to checked #}

        {% if template is defined and template == 'filter' %}
          
        {% else %}
          
        {% endif %}
        {{ category.title }}
      
    {% endfor %}
  {% endif %}

  Submit



The Filter Results Page
On the results page you need to check which filter variables have been set via the get request and then display the appropriate related entries.
{# set park search parameters #}
{% set park1 = craft.request.getParam('park1') %}
{% set park2 = craft.request.getParam('park2') %}
{% set park3 = craft.request.getParam('park3') %}
{% set park4 = craft.request.getParam('park4') %}
{% set park5 = craft.request.getParam('park5') %}

{# set price search parameters #}
{% set price1 = craft.request.getParam('price1') %}
{% set price2 = craft.request.getParam('price2') %}
{% set price3 = craft.request.getParam('price3') %}
{% set price4 = craft.request.getParam('price4') %}
{% set price5 = craft.request.getParam('price5') %}
{% set price6 = craft.request.getParam('price6') %}

{# set park category model if it is in the search query #}
{% set parkCategory1 = park1|length ? craft.categories.slug(park1).first().id %}
{% set parkCategory2 = park2|length ? craft.categories.slug(park2).first().id %}
{% set parkCategory3 = park3|length ? craft.categories.slug(park3).first().id %}
{% set parkCategory4 = park4|length ? craft.categories.slug(park4).first().id %}
{% set parkCategory5 = park5|length ? craft.categories.slug(park5).first().id %}

{# create an array of park categories #}
{% set parks = [
  parkCategory1,
  parkCategory2,
  parkCategory3,
  parkCategory4,
  parkCategory5,
] %}

{# create a park array and trim blank strings #}
{% set trimParks = [] %}

{% for park in parks %}
  {% if park|length %}
    {% set trimParks = trimParks|merge({ (loop.index0): park}) %}
  {% endif %}
{% endfor %}

{# set price category model if it is in the search query #}
{% set priceCategory1 = price1|length ? craft.categories.slug(price1).first().id %}
{% set priceCategory2 = price2|length ? craft.categories.slug(price2).first().id %}
{% set priceCategory3 = price3|length ? craft.categories.slug(price3).first().id %}
{% set priceCategory4 = price4|length ? craft.categories.slug(price4).first().id %}
{% set priceCategory5 = price5|length ? craft.categories.slug(price5).first().id %}
{% set priceCategory6 = price6|length ? craft.categories.slug(price6).first().id %}

{# create an array of price categories #}
{% set prices = [
  priceCategory1,
  priceCategory2,
  priceCategory3,
  priceCategory4,
  priceCategory5,
  priceCategory6,
] %}

{# create a price array and trim blank strings #}
{% set trimPrices = [] %}

{% for price in prices %}
  {% if price|length %}
    {% set trimPrices = trimPrices|merge({ (loop.index0): price}) %}
  {% endif %}
{% endfor %}

{% if trimParks|length and trimPrices|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('and',
    {targetElement:parks},
    {targetElement:prices}
  ) %}
{% endif %}

{% if trimParks|length and not trimPrices|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('or',
    {targetElement:parks}
  ) %}
{% endif %}

{% if trimPrices|length and not trimParks|length %}
  {% set entries = craft.entries.section('homesForSale').relatedTo('or',
    {targetElement:prices}
  ) %}
{% endif %}

Filter Results

{% if entries|length %}
    {{ entries|length }} results:
    
        {% for entry in entries %}
          {% set park = entry.park.first() %}
          {% set price = entry.parkPriceCategory.first() %}
          {{ entry.title }} :: {{ park }} :: {{ price }}
        {% endfor %}
    
{% else %}
    Your search didn't return any results.
{% endif %}


---

