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) %}
Jammooka
  • 82
  • 8
  • 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? https://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 08: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 08:34

1 Answers1

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 %}
carlcs
  • 36,220
  • 5
  • 62
  • 139
  • 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 http://craftcms.stackexchange.com/questions/51/how-do-you-sort-elements-queried-from-multiple-channels/78#78 – carlcs Mar 21 '16 at 21:33
  • Hahha you're everywhere! Top man – Jammooka Mar 22 '16 at 08:45