<p>It's currently not possible to combine criteria params like this (see <a href="https://craftcms.stackexchange.com/questions/1948/complex-logic-on-a-elementcriteriamodel-parameter">Complex logic on a ElementCriteriaModel parameter?</a>).
As a workaround you'd prepare an <code>idParam</code> object, similar to your <code>relatedToParam</code> and collect all matching element IDs
making use of additional criteria models and the <code>ids</code> method.</p>

<pre><code>{# Prep the id param #}
{% set idParam = [] %}

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

    {% set pbackEntryIds = craft.entries({
        section: 'books',
        paperbackRrp: 'and, &gt; '~price_from~', &lt; '~price_to
    }).ids() %}

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

{# Merge in the id param #}
{% if idParam|length %}
    {% set params = params|merge({ id: idParam }) %}
{% endif %}
</code></pre>

CC BY-SA 3.0
2016-03-21T18:59:17.273Z
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
CC BY-SA 3.0
2016-03-21T21:33:13.217Z
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
CC BY-SA 3.0
2016-03-22T08:45:04.520Z
Hahha you're everywhere! Top man
Jammooka
CC BY-SA 3.0
2016-03-21T08:46:00.193Z
2016-03-21T08:46:00.193Z
2017-04-13T12:51:00.303Z
carlcs
<p>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 <code>craft.entries(params)</code>.</p>

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

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

<pre><code>{% if 'ebook' in formats %}
    {% set params = params|merge({ 'ebookRrp' : 'and, &gt; '~price_from~', &lt; '~price_to }) %}
{% endif %}
{% if 'pback' in formats %}
    {% set params = params|merge({ 'paperbackRrp' : 'and, &gt; '~price_from~', &lt; '~price_to }) %}
{% endif %}
</code></pre>

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

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

<pre><code>{% set params = params|merge(['or',
    { 'ebookRrp' : 'and, &gt; '~price_from~', &lt; '~price_to },
    { 'paperbackRrp' : 'and, &gt; '~price_from~', &lt; '~price_to }
]) %}
</code></pre>

<p>Any ideas?</p>

<p>--- Update with full code: ---</p>

<pre><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 &gt; 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, &gt; '~price_from~', &lt; '~price_to }) %}
{% endif %}
{% if 'pback' in formats %}
    {% set params = params|merge({ 'isPaperback' : 1 }) %}
    {% set params = params|merge({ 'paperbackRrp' : 'and, &gt; '~price_from~', &lt; '~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, &gt; '~price_from~', &lt; '~price_to },
        { 'paperbackRrp' : 'and, &gt; '~price_from~', &lt; '~price_to }
    ]) %}
{% endif %}
#}

{# Finally get the relevant books #}
{% set books = craft.entries(params) %}
</code></pre>

CC BY-SA 3.0
2016-03-18T23:10:21.020Z
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
CC BY-SA 3.0
2016-03-19T08:28:31.540Z
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
CC BY-SA 3.0
2016-03-19T08:34:44.117Z
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
<entries><custom-field>
Combining custom field filters on craft.entries
# Combining custom field filters on craft.entries

(Asked by: username_0 on 2016-03-18)

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) %}

**Tags:** entries, custom-field

> **Comments:**
> **username_1**: 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  
> **username_0**: 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.  
> **username_0**: 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.  

---

## 1 answers

### Answer by username_2 on 2016-03-21. Score: 0 | Accepted answer

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 %}

> **Comments:**
> **username_0**: 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!  
> **username_2**: 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  
> **username_0**: Hahha you're everywhere! Top man  

---

