3

I have created a search form which allows user to search multiple categories groups and multiple categories within those groups.

So I have

Type 

[] Category 1

[x] Category 2

[] Category 3

...


Location

[] Category 1

[x] Category 2

[] Category 3

[] Category 4

I've chosen to use slugs as the search parameter for usability purposes but that means that I have to get the element of each slug and then pass it into the entries query. Long story short,lots of queries to my database before I even get started outputting the categories above.

I'm interested in caching the category queries and I'm doing as follows

{% cache using key "restaurant-filter-type" %}

    {% set typeList = craft.categories.group('restaurantType') %}

    {% for type in typeList %}

        <div class="field field--checkbox">
            <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}">
            <label for="{{ type.slug }}">{{ type.title }}</label>
        </div>

   {% endfor %}

{% endcache %}

The problem I run into is when the user submits the form and the checked form elements arent being persistent because of the caching I've set.

I've tried looking at this SE question to help but the stumbling block for this is that there is the possibility that the parameter holding my restaurant type slugs may hold multiple values, hence the name="type[]". A simple replace filter doesn't look likely to work in that situation.

Would anyone have any ideas how I could get around this?

2
  • Are the parameters added to the URL as query strings when you submit the form (using GET method) ? If they are you should use the full URL in your cache key so that a different cache is created for each. Jul 25 '15 at 7:00
  • Yes it is, i just look it out for brevity. Jul 25 '15 at 11:47
4
+50

There're various ways of doing this. The simplest would be to just use the submitted slugs to generate a new cache key for each different search, like Jamie suggests. This is a very straightforward and readable solution, which in most cases would probably yield a "good enough" performance boost. You'd simply create a key based on the params that are used in your cached content, so something like (could be made a bit less verbose if you prefer):

{% set submittedTypesArray = craft.request.getParam('type') %}
{% set submittedTypesString = submittedTypesArray | join('-') %}

{% cache using key "restaurant-filter-type-" ~ submittedTypesString %}
    {% set typeList = craft.categories.group('restaurantType') %}

    {% for type in typeList %}
        <div class="field field--checkbox">
            <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}"{% if type.slug in submittedTypesArray %} checked{% endif %}>
            <label for="{{ type.slug }}">{{ type.title }}</label>
        </div>
    {% endfor %}
{% endcache %}

The backdraw of this solution is that it generates one cache entry for every different combination of the types. If this is "good enough" depends on your project.

If you want to use the approach naboovalley describes in the linked answer, here is a rewrite for your usecase:

{% set typeCategories %}
    {% cache using key "restaurant-filter-type" %}
        {% set typeList = craft.categories.group('restaurantType') %}

        {% for type in typeList %}
            <div class="field field--checkbox">
                <input type="checkbox" name="type[]" id="{{ type.slug }}" value="{{ type.slug }}" data-type-{{ type.slug }}>
                <label for="{{ type.slug }}">{{ type.title }}</label>
            </div>
        {% endfor %}
    {% endcache %}
{% endset %}

{% set types = craft.request.getParam('type') %}    
{% for type in types %}
    {% set typeCategories = typeCategories | replace('data-type-' ~ type, 'checked')  %}
{% endfor %}

{{ typeCategories }}

It would be possible to do this with several category groups inside one variable/cache entry, but you'd have to give them different data-names to make sure that you don't run into problems if two categories in different groups have the same slug.

I'm sure there's a wicked elegant way to do the replace without the for loop, I just couldn't wrap my head around it right now. ;)

And, just to add more options, if this was a really high traffic site (or the server that hosts the site is really crappy), I'd actually update the status of the checkboxes with javascript on the client, instead of doing it with Craft. Even though it would maybe annoy a user that has javascript turned off and has to check all the checkboxes for every search, nothing would break. And you can't beat the performance of doing something on the client instead of on the server.

0

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.