4

I'm building an advanced search form and having some difficulty with getting the results. The form inputs include price and year ranges. For example, search for used cars from $10,000 to $20,000.

The search is working, here's my results page code:

{% set manufacturer = craft.request.getParam('manufacturer') %}
{% set model = craft.request.getParam('model') %}
{% set bodyStyle = craft.request.getParam('bodyStyle') %}

{% set minPrice = craft.request.getParam('minPrice') %}
{% set maxPrice = craft.request.getParam('maxPrice') %}

{% set startYear = craft.request.getParam('startYear') %}
{% set endYear = craft.request.getParam('endYear') %}

{% set results = craft.entries.section('usedCars').type('entry').search().manufacturer(manufacturer).model(model).bodyStyle(bodyStyle) %}

This is how i'm showing the price range.

{% if minPrice|length and maxPrice|length %}
{% for entry in results if entry.price <= maxPrice and entry.price >= minPrice %}

{% if minPrice is empty and maxPrice|length %}
{% for entry in results if entry.price <= maxPrice %}

and so on etc...

The trouble with this method is it's all based on a whole stack of "IF" statements and when I start to think about adding the year ranges too, my head starts to hurt. Is there an easier way to achieve the same thing?

I'd appreciate any nod in a general direction, or help simplifying my code down...

2 Answers 2

10

You can set multiple conditions on a single ElementCriteriaModel parameter. Pass it either a comma-separated list as a string or an array of conditions.

{% set entries = craft.entries.id('84, 62, < 7, 29') %}
{% set entries = craft.entries.id([84, 62, < 7, 29]) %}

In this example, each entry with any of these IDs is returned (→ or logic). To return only those entries that match all criteria of your list (→ and logic), set the first value to and:

{% set entries = craft.entries.id('and, > 100, < 200, not 110') %}

In your case I'd set the "year" and "price" parameters as an array and combine it with all other craft.entries parameters using the object syntax like so:

{% set entries = craft.entries({

    section: 'usedCars',
    type: 'entry',
    manufacturer: manufacturer,
    model: model,
    bodyStyle: bodyStyle,
    price: [
        'and',
        '>= ' ~ minPrice,
        '<= ' ~ maxPrice,
    ],
    year: [
        'and',
        '>= ' ~ startYear,
        '<= ' ~ endYear,
    ],

}) %}

Make sure that your "year" and "price" variables are not empty by setting default values:

{% set startYear = craft.request.getParam('startYear') %}
{% set startYear = startYear is not empty ? startYear : '1900' %}
2
  • Thanks Carlcs! Works perfectly, really appreciate it. I hadn't realised you could set multiple conditions on a single ElementCriteriaModel parameter. Some great learnings in your answer.
    – R0wan
    Nov 5, 2014 at 22:23
  • How can we make params on condition llike if data entered by user only than filter .craftcms.stackexchange.com/questions/30188/…
    – inrsaurabh
    Apr 17, 2019 at 12:23
3

If statements should be fine. What you're building is a query to find things later. So you could easily start with the query:

{% set query = craft.entries.section('usedCars').type('entry') %}

Then add parameters as they exist:

{% if craft.request.getParam('manufacturer') %}
    {% set query = query.manufacturer(craft.request.getParam('manufacturer')) %}
{% endif %}

Also, I don't see an actual search query (like from a search box). If you're just searching based on predefined parameters, you don't need to add search(). That's mainly for full text searching.

When you're all set, you can then check for results:

{% if query.total() %}

And display them if there's any:

{% for car in query %}
    {{ car.title }}
{% endfor %}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.