1

I'm building a book store which filters entries based on GET variables. For the most part, this is working well just merging in various filters to a params variable and then passing craft.entries(params).

The tricky bit is that each book can have an ebook price and a paperback price.

If the books are being filtered to a certain format, then I just do this:

{% if 'ebook' in formats %}
    {% set params = params|merge({ 'ebookRrp' : 'and, > '~price_from~', < '~price_to }) %}
{% endif %}
{% if 'pback' in formats %}
    {% set params = params|merge({ 'paperbackRrp' : 'and, > '~price_from~', < '~price_to }) %}
{% endif %}

That works well for an individual format, but if no format is selected it becomes too specific.

It seems like I need to do something like the following, but this doesn't seem to have any effect on what is returned:

{% set params = params|merge(['or',
    { 'ebookRrp' : 'and, > '~price_from~', < '~price_to },
    { 'paperbackRrp' : 'and, > '~price_from~', < '~price_to }
]) %}

Any ideas?

--- Update with full code: ---

{# Prep the entries params #}
{% set params = {
    section: 'books',
    with: [
        'bookAuthor',
        'booksImage',
    ]
} %}

{# Prep the relatedTo params #}
{% set relatedToParams = ['and'] %}

{# need to do a bunch of checks here and combine them into one relatedto query #}

{% if craft.request.getParam('author') %}
    {% set relatedToParams = relatedToParams|merge([{
        targetElement: craft.request.getParam('author'),
        field: 'bookAuthor'
    }]) %}
{% endif %}

{% if entry.section.handle == 'collections' %}
    {% set relatedToParams = relatedToParams|merge([{
        sourceElement: entry
    }]) %}
{% endif %}

{% if craft.request.getParam('genre') %}
    {% set relatedToParams = relatedToParams|merge([{
        targetElement: ['and']|merge(craft.request.getParam('genre')),
        field: 'genre'
    }]) %}
{% endif %}

{# Merge in the relatedTo params if they exist #}
{% if relatedToParams|length > 1 %}
    {% set params = params|merge({ 'relatedTo' : relatedToParams }) %}
{% endif %}

{% set maxPrice = 10000 %} {# temp high number before working out highest value #}
{% set price_from = craft.request.getParam('price_from') ?? 0 %}
{% set price_to = craft.request.getParam('price_to') ?? maxPrice %}

{% set formats = craft.request.getParam('format') ?? null %}
{% if 'ebook' in formats %}
    {% set params = params|merge({ 'isEbook' : 1 }) %}
    {% set params = params|merge({ 'ebookRrp' : 'and, > '~price_from~', < '~price_to }) %}
{% endif %}
{% if 'pback' in formats %}
    {% set params = params|merge({ 'isPaperback' : 1 }) %}
    {% set params = params|merge({ 'paperbackRrp' : 'and, > '~price_from~', < '~price_to }) %}
{% endif %}

{# 
{% if formats is null %}
    somehow filter price for both formats as an or?
    This doesn't work:
    {% set params = params|merge(['or',
        { 'ebookRrp' : 'and, > '~price_from~', < '~price_to },
        { 'paperbackRrp' : 'and, > '~price_from~', < '~price_to }
    ]) %}
{% endif %}
#}

{# Finally get the relevant books #}
{% set books = craft.entries(params) %}
  • Couldn't you just use a switch statement and have the default format be whatever values you want to use if no format is selected? craftcms.com/docs/templating/switch – Brad Bell Mar 18 '16 at 23:10
  • If no format is selected, then it should return all books regardless of format. The issue is that if I filter by ebookRrp AND paperbackRrp, then it returns only those books that match both, not one or the other. Perhaps it would help if I showed my full filtering code? I will update. – Jammooka Mar 19 '16 at 8:28
  • I've added the full filter code as it currently stands. The bit that I can't suss out is the if formats is null section that is commented out. – Jammooka Mar 19 '16 at 8:34
0

It's currently not possible to combine criteria params like this (see Complex logic on a ElementCriteriaModel parameter?). As a workaround you'd prepare an idParam object, similar to your relatedToParam and collect all matching element IDs making use of additional criteria models and the ids method.

{# Prep the id param #}
{% set idParam = [] %}

{% if formats is null %}
    {% set ebookEntryIds = craft.entries({
        section: 'books',
        ebookRrp: 'and, > '~price_from~', < '~price_to
    }).ids() %}

    {% set pbackEntryIds = craft.entries({
        section: 'books',
        paperbackRrp: 'and, > '~price_from~', < '~price_to
    }).ids() %}

    {% set idParam = ebookEntryIds|merge(pbackEntryIds) %}
{% endif %}

{# Merge in the id param #}
{% if idParam|length %}
    {% set params = params|merge({ id: idParam }) %}
{% endif %}
  • This is definitely better than any approach I've come up with yet. Now I just need to find a way to calculate the most expensive book... Starting to regret suggesting so many filters! Thanks! – Jammooka Mar 21 '16 at 18:59
  • 1
    This should help with your sort order problem craftcms.stackexchange.com/questions/51/… – carlcs Mar 21 '16 at 21:33
  • Hahha you're everywhere! Top man – Jammooka Mar 22 '16 at 8:45

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.