<p>Untested, but something like this should work:</p>

<pre><code>{# set base criteria #}
{% set params = {
    section: 'productsServices',
    limit: null
} %}

{# set relationship criteria #}
{% set relationParam = ['and'] %}
{% for segment in craft.request.segments %}
    {% if loop.index != 1 and segment != 'all' %}
        {% set category = craft.categories.slug(segment).first() %}
        {% set relationParam = relationParam|merge([{ targetElement:category }]) %}
    {% endif %}
{% endfor %}

{# check to ensure that at least one relationship is defined and merge criteria #}
{% if relationParam|length &gt; 1 %}
    {% set params = params|merge({relatedTo: relationParam}) %}
{% endif %}

{# retrieve entries #}
{% set entries = craft.entries(params) %}
{% for entry in entries %}
    {{ entry.title }}
    ...
{% endfor %}
</code></pre>

<p><strong>Update</strong> Added a check to ensure that not all segments are set to 'all'; Fixed 'length' syntax.</p>

<p>Give credit to carlcs and his <a href="https://craftcms.stackexchange.com/questions/5107/users-relatedto-multiple-categories/5108#5108">ElementCriteriaModel Fu in this answer</a>.</p>

CC BY-SA 3.0
2014-12-19T06:59:09.520Z
Thanks - not just working yet though - does that work as an AND or OR - I'm still getting all items returned that don't match all criteria.
For this URL: /products-services/inks/concrete/quality-assurance
if I do a dump on relationParam I get:
array(2) { [0]=> string(3) "and" ["targetElement"]=> string(17) "quality-assurance" } 
should I not be seeing the first couple of parameters there?
Does relatedTo need to be included anywhere or is that automatic. Been trying different variations myself, but just not getting it right
mmc501
CC BY-SA 3.0
2014-12-19T07:48:58.910Z
Inside the loop I tried this:
{% set segcategory = craft.categories.slug(segment).first() %}
{% set relationParam = relationParam|merge({ targetElement:segcategory }) %}

Setting params: 
{% if relationParam|length > 1 %}
    {% set params = { section: 'productsServices', relatedTo: relationParam } %}
{% else %}
    {% set params = { section: 'productsServices' } %}
{% endif %}

But it will only take the last parameter of the url into account and return those entries.
mmc501
CC BY-SA 3.0
2014-12-19T08:20:56.663Z
Your right about the `relatedTo`. Good catch. I updated that. Regarding only picking up the last segment — it looks like `relationParam|merge([{ targetElement:segment }])` needs to be wrapped in brackets. See if this doesn't work better. And yes, that works as an 'AND'.
Douglas McDonald
CC BY-SA 3.0
2014-12-19T08:47:05.680Z
Excellent - only think I needed to add was to relate the segment back to the category - and it all worked. Inside the loop I needed:
    `set segcategory = craft.categories.slug(segment).first()` 
then     `{% set relationParam = relationParam|merge([{ targetElement:segcategory }]) %}`
mmc501
CC BY-SA 3.0
2014-12-19T09:01:25.243Z
Great! I updated the code with that change as well. Sorry about some of the errors. Always hard to do this blind.
Douglas McDonald
CC BY-SA 3.0
2014-12-19T09:02:50.283Z
Ah errors grand - helps me learn in the process! Thanks!!
mmc501
CC BY-SA 3.0
2014-12-18T19:28:16.903Z
2014-12-19T08:59:59.317Z
2017-04-13T12:50:59.930Z
Douglas McDonald
<p>Trying to build a complex query and I'm sure there is bound to be a better way of doing it that the multiple if statements I currently have.
URL for the page is /products/(category1)/(category2)/(category3)</p>

<p>if any of the categorys in the url is selected it will display that slug other wise it will be all e.g.
/products/inks/glass/all
/products/all/glass/catname</p>

<p>I have been doing this:</p>

<pre><code>{# get categories #}
  {% set catTypeSlug = craft.request.getSegment(2) %}
  {% if catTypeSlug != 'all' %}
  {% set catType = craft.categories.slug(catTypeSlug).first() %}
  {% endif %}

  {% set catSurfaceSlug = craft.request.getSegment(3) %}
  {% if catSurfaceSlug != 'all' %}
  {% set catSurface = craft.categories.slug(catSurfaceSlug).first() %}
  {% endif %}

  {% set catUseSlug = craft.request.getSegment(4) %}
  {% if catUseSlug != 'all' %}
  {% set catUse = craft.categories.slug(catUseSlug).first() %}
  {% endif %}


  {# set parameters #}
  {% if catType is defined and catSurface is defined and catUse is defined %}
    {% set params = { section: 'productsServices', relatedTo: catType, relatedTo: catSurface, relatedTo: catUse } %}

  {% else %}  
    {# multiple if statements checking if categories defined #}

  {% endif %}  
</code></pre>

<p>What's the best way to build my parameters instead of multiple if statements?</p>

<entries><elementcriteriamodel><params>
Build Query relatedTo multiple categories
# Build Query relatedTo multiple categories

(Asked by: username_0 on 2014-12-18)

Trying to build a complex query and I'm sure there is bound to be a better way of doing it that the multiple if statements I currently have.
URL for the page is /products/(category1)/(category2)/(category3)
if any of the categorys in the url is selected it will display that slug other wise it will be all e.g.
/products/inks/glass/all
/products/all/glass/catname
I have been doing this:
{# get categories #}
  {% set catTypeSlug = craft.request.getSegment(2) %}
  {% if catTypeSlug != 'all' %}
  {% set catType = craft.categories.slug(catTypeSlug).first() %}
  {% endif %}

  {% set catSurfaceSlug = craft.request.getSegment(3) %}
  {% if catSurfaceSlug != 'all' %}
  {% set catSurface = craft.categories.slug(catSurfaceSlug).first() %}
  {% endif %}

  {% set catUseSlug = craft.request.getSegment(4) %}
  {% if catUseSlug != 'all' %}
  {% set catUse = craft.categories.slug(catUseSlug).first() %}
  {% endif %}


  {# set parameters #}
  {% if catType is defined and catSurface is defined and catUse is defined %}
    {% set params = { section: 'productsServices', relatedTo: catType, relatedTo: catSurface, relatedTo: catUse } %}

  {% else %}  
    {# multiple if statements checking if categories defined #}

  {% endif %}  

What's the best way to build my parameters instead of multiple if statements?

**Tags:** entries, elementcriteriamodel, params

---

## 1 answers

### Answer by username_1 on 2014-12-18. Score: 6 | Accepted answer

Untested, but something like this should work:
{# set base criteria #}
{% set params = {
    section: 'productsServices',
    limit: null
} %}

{# set relationship criteria #}
{% set relationParam = ['and'] %}
{% for segment in craft.request.segments %}
    {% if loop.index != 1 and segment != 'all' %}
        {% set category = craft.categories.slug(segment).first() %}
        {% set relationParam = relationParam|merge([{ targetElement:category }]) %}
    {% endif %}
{% endfor %}

{# check to ensure that at least one relationship is defined and merge criteria #}
{% if relationParam|length > 1 %}
    {% set params = params|merge({relatedTo: relationParam}) %}
{% endif %}

{# retrieve entries #}
{% set entries = craft.entries(params) %}
{% for entry in entries %}
    {{ entry.title }}
    ...
{% endfor %}

Update Added a check to ensure that not all segments are set to 'all'; Fixed 'length' syntax.
Give credit to carlcs and his ElementCriteriaModel Fu in this answer.

> **Comments:**
> **username_0**: Thanks - not just working yet though - does that work as an AND or OR - I'm still getting all items returned that don't match all criteria. For this URL: /products-services/inks/concrete/quality-assurance if I do a dump on relationParam I get: array(2) { [0]=> string(3) "and" ["targetElement"]=> string(17) "quality-assurance" }  should I not be seeing the first couple of parameters there? Does relatedTo need to be included anywhere or is that automatic. Been trying different variations myself, but just not getting it right  
> **username_0**: Inside the loop I tried this: {% set segcategory = craft.categories.slug(segment).first() %} {% set relationParam = relationParam|merge({ targetElement:segcategory }) %}  Setting params:  {% if relationParam|length > 1 %}     {% set params = { section: 'productsServices', relatedTo: relationParam } %} {% else %}     {% set params = { section: 'productsServices' } %} {% endif %}  But it will only take the last parameter of the url into account and return those entries.  
> **username_1**: Your right about the `relatedTo`. Good catch. I updated that. Regarding only picking up the last segment — it looks like `relationParam|merge([{ targetElement:segment }])` needs to be wrapped in brackets. See if this doesn't work better. And yes, that works as an 'AND'.  
> **username_0**: Excellent - only think I needed to add was to relate the segment back to the category - and it all worked. Inside the loop I needed:     `set segcategory = craft.categories.slug(segment).first()`  then     `{% set relationParam = relationParam|merge([{ targetElement:segcategory }]) %}`  
> **username_1**: Great! I updated the code with that change as well. Sorry about some of the errors. Always hard to do this blind.  
> **username_0**: Ah errors grand - helps me learn in the process! Thanks!!  

---

