Good afternoon, I am writing a smart filter for the site by analogy with Yandex.Market. Actually that day, the implementation of the relative filter was puzzled.

What we have:

Dynamic form: (The form is generated automatically, but for clarity, inserted HTML)

<form method="get" action=""> <div> <label>Asus</label> <input type="checkbox" name="filter[]" value="Asus"> <label>Acer</label> <input type="checkbox" name="filter[]" value="Acer"> <label>Lenovo</label> <input type="checkbox" name="filter[]" value="Lenovo"> </div> <div> <label>2015</label> <input type="checkbox" name="filter[]" value="2015"> <label>2014</label> <input type="checkbox" name="filter[]" value="2014"> <label>2013</label> <input type="checkbox" name="filter[]" value="2013"> </div> <button>Искать</button> </form> 

After submitting the form there is a url of the following form:

 site.com?filter=Asus&filter=2015 

We also have tables in the database:

 products (id, title) products_to_filter (id, product_id, filter_id) 

The handler itself looks like this (PS Laravel framework)

 Выборка соответствующих фильтров. $filter[] = explode(',', $request->input('filter'); $filters = DB::table('products_to_filter')->whereIn('id', $filter) ->get() ->all(); foreach($filters as $row) {$filterArray[] = $row->product_id;} Выборка продуктов: $products = DB::table('products')->whereIn('id', $filterArray)->get()->all(); 

Actually, my problem is the following, the filter works, but not quite as I need, tobish when filtering, it should reduce the results, but on the contrary it searches for more depth, and as a result increases the number of results. How to solve this problem?

    1 answer 1

    You incorrectly form $filterArray - it's all too simple. Now the condition you get is:

    Select a product_id that matches at least one selected item.

    If you change the logic to

    Select product_id that matches all selected items.

    then it will also be a mistake (well, after all, the manufacturer and Acer and Asus cannot have the same product). An error has crept into the very idea of ​​constructing a form. Items (filters) need to be collected in groups (manufacturer, year of release, etc.). And the logic of building $filterArray should sound like this:

    Select product_id that matches all selected filter groups. Matching a group is matching at least one of the group filters.

    I am not very strong in Laravel but the idea is this:

     // Допустим получаем из формы массив вот такого вида $filtersgroup = array( 'manufacturer' => array(21, 22, 23), 'year' => array(37, 48), 'type' => array(51, 54, 59), ); // Для построения запроса нам понадобится иметь номера таблиц, для связи с первой $ix = 1; foreach ($filtersgroup as $filtersId) { $alias = 'pf' . $ix; if (1 == $ix) { $query = DB::table('product_to_filter AS pf1'); } else { // Каждую последующую таблицу связываем с первой $query = $query->join('product_to_filter AS ' . $alias, 'pf1.product_id', '=', $alias . '.product_id'); } // Добавляем условие для каждой группы $query = $query->whereIn($alias . '.product', $filtersId); $ix += 1; } // Выполняем запрос, получаем список product_id $filterArr = $query->select('pf1.product_id')->distinct()->pluck('product_id')} 

    In principle, you can add the first products table and get a ready-made list of products as a result of a query

    • Can you demonstrate the correct construction algorithm? - asd
    • @asd, completed the answer - tutankhamun