3

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?

5

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.

| improve this answer | |
  • 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 Dec 19 '14 at 6:59
  • 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 Dec 19 '14 at 7:48
  • 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 Dec 19 '14 at 8:20
  • 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 Dec 19 '14 at 8:47
  • Great! I updated the code with that change as well. Sorry about some of the errors. Always hard to do this blind. – Douglas McDonald Dec 19 '14 at 9:01

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.