Релятивный фильтр PHP

176
10 декабря 2016, 10:07

Добрый день, пишу для сайта умный фильтр по аналогии Яндекс.Маркета. Собственно уже который день озадачился вопросом реализация релятивного фильтра.

Что имеем:

Динамическую форму: (Форма генерируется автоматически, но для наглядности вставил 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>

После сабмита формы имеется url следующего вида:

site.com?filter=Asus&filter=2015

Так же имеем таблицы в базе данных:

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

Сам обработчик выглядит следующим образом (P.S фреймворк Laravel)

Выборка соответствующих фильтров.
$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();

Собственно моя проблема заключается в следующем, фильтр работает, но не совсем так как мне нужно, тобишь при фильтрации, он должен результаты уменьшать, а он же наоборот ищет более углубленно, и как следствие увеличивает кол-во результатов. Как решить данную проблему?

Answer 1

Вы неправильно формируете $filterArray - слишком это все просто. Сейчас условие которое вы получате звучит так:

Выбрать product_id, которые соответствуют хотя бы одному выбранному пункту

Если вы поменяете логику на

Выбрать product_id, которые соответствуют всем выбранным пунктам

то это тоже будет ошибкой (ну ведь не может же быть у одного и того же продукта производителем и Acer и Asus). В саму идею построения формы вкралась ошибка. Пункты (фильтры) нужно собирать в группы (производитель, год выпуска и т. д). И логика построения $filterArray должна звучать так:

Выбрать product_id, которые соответствуют всем выбранным группам фильтров. Соответствие группе - это соответствие хотя бы одному из фильтров группы.

Дополнено Я не очень силен в Laravel но идея вот такая:

// Допустим получаем из формы массив вот такого вида
$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')}

В принципе можно добавить первой таблицу products и получать в результате запроса уже готовый список "продуктов"

READ ALSO
Не загружаются файлы на сервер через скрипт

Не загружаются файлы на сервер через скрипт

Пытаюсь использовать готовый php скрипт для загрузки аватарок на сервер

149
php-google-spreadsheet-client

php-google-spreadsheet-client

Установил через composer библиотеку php-google-spreadsheet-client для работы с google таблицамиПри попытке обратится к таблице получаю ошибку

197
Отправка письма PHP

Отправка письма PHP

Имеется HTML разметка

341