Looking for the solution to searching entries in one section that are related to multiple categories and match number field criteria. This is for a used auto website.
Categories:
Make/Model/Trim: Nested category levels for better searching a leveling of vehicles. Category example: Chevrolet -> Malibu -> LS
Transmission: Automatic and Manual
Class: Coupe, Sedan, SUV, etc...
Fields: Price - number field with up to 2 decimal places. Year - 4 digit number no punctuation or decimal places.
The search bar fields: Make Model Transmission Class Minimum Year Maximum Year Minimum Price Maximum Price
Current search form submits a url such as: http://examplesite.com/search?make=chevrolet&model=malibu&transmission=automatic&min-year=2007&max-year=2017&min-price=3000&max-price=20000&class=sedan
Whether or not a search field was used it still applies at empty field to the url.
I've read every Craft CMS Multi search page and SO question on this as well as the new Craft CMS 3 documentation. I can't seem to find solution to the categories part first off and then a decent way to handle the number criteria. Also, I am planning on paginating the entries (causes a separate issue of not being able to use loop.last, which I can solve with some loop counters).
Current search page code:
{% set make = craft.app.request.getParam('make') %}
{% set model = craft.app.request.getParam('model') %}
{% set transmission = craft.app.request.getParam('transmission') %}
{% set class = craft.app.request.getParam('class') %}
{% set minYear = craft.app.request.getParam('min-year') %}
{% set maxYear = craft.app.request.getParam('max-year') %}
{% set minPrice = craft.app.request.getParam('min-price') %}
{% set maxPrice = craft.app.request.getParam('max-price') %}
{% set makeCat = make ? craft.categories.group('makeModelTrim').slug(make).find() %}
{% set modelCat = model ? craft.categories.group('makeModelTrim').slug(model).find() %}
{% set transmissionCat = transmission ? craft.categories.group('transmission').slug(transmission).find() %}
{% set classCat = class ? craft.categories.group('class').slug(class).find() %}
{% set makeParam = makeCat ? {targetElement: ['and']|merge(makeCat)} %}
{% set modelParam = modelCat ? {targetElement: ['and']|merge(modelCat)} %}
{% set transmissionParam = transmissionCat ? {targetElement: ['and']|merge(transmissionCat)} %}
{% set classParam = classCat ? {targetElement: ['and']|merge(classCat)} %}
{% set relationParams = [makeParam, modelParam, transmissionParam, classParam]|filter %}
{% set entries = craft.entries({section: 'vehicles',relatedTo: relationParams ? ['and']|merge(relationParams) : null}) %}
Works but is kinda wonky. I would like the related entries to match all of the given categories but it currently pulls vehicles that match any of the categories. If Chevrolet and Automatic transmission are given criteria, both Chevrolets and Automatics are pulled which is not what I want.
Is there a way to add the min/max year and price to the related to parameters? If so then that would solve the next issue of sorting through the entries though it's difficult to paginate the entries if I have to throw out some retrieved ones after the fact. When I try to convert the set entries to paginate with this:
{% paginate craft.entries({section: 'vehicles',relatedTo: relationParams ? ['and']|merge(relationParams) : null}).limit(12) as pageInfo, pageEntries %}
It doesn't seem to work though I can get the count of pageEntries and it will return some number. But what I'm currently doing is the former setting of the entries to the related parameters then running this:
{% for vehicle in pageEntries if minYear|length and minYear <= vehicle.year and maxYear|length and maxYear >= vehicle.year and minPrice|length and minPrice <= vehicle.price and maxPrice|length and maxPrice >= vehicle.price %}
Which doesn't work. I'm guessing that my if statements aren't in order or can't be used that way. I could have a complicated if/else or case scenario to handle whether min/max price and year have been set rather than checking it in the for loop, though I'm not certain what's best.
I'm sure someone reading this has a simple solution to multi category and multi field entry searching. And if it's possible to eliminate the the empty parameters in the url, that would be helpful as well. I currently have empty options with no values set holding the place of the select drop-downs until a value is selected.
relatedTo
parameter? You can set this parameter via magic settercraft.entries.minPrice('>=50').maxPrice('<=100).minYear(>=2004).maxYear('<=2016).all()
however. I'm usually no fan of complex search functions in twig because of certain experiences in the past years. It's much easier to extend the query more freely and flexible via php in order to joinrelation
tables on your own to build more complex nested relationshipsentry.fieldHandle
is a magic getter too. Usually you won't see any search result here on Stack Exchange for similar questions without them.