• Портфолио
  • Услуги
  • Цены
  • Контакты
Веблог

Поиск по tv-параметрам в CatalogView

Веблог » Поиск по tv-параметрам в CatalogView

В одном из проектов передо мной стояла задача сделать поиск по каталогу Shopkeeper, где к каждому из товаров присваивается множество различных tv-параметров. Товары выводятся с помощью сниппета CatalogView.

В чем собственно была проблема, в данном сниппете можно сортировать товары через параметр filter или выводить только необходимы через where. Но так как значение для каждого из tv-параметров хранится в отдельной ячейке таблицы, не получалось задавать сразу несколько условий поиска. Происходила сортировка по логическому «ИЛИ», но не удавалось сделать по логическому «И». Это в общем и понятно, получалось что даже если использовался объединяющий два условия AND, поиск обоих частей условия происходил в одной ячейке таблицы базы данных.

Выход был найден такой – были написаны подзапросы к базе данных, результаты которых группируются в отдельную временную таблицу, и из этой таблицы выбираются необходимые данные. В случае если поиск идет по 2 tv, то выбираются товары, встречающиеся в данной таблице более чем 1 раз, если по 2 tv, то более 2 раз и так далее. Почему именно так? Получается, что при поиске по параметрам находятся ID товаров, которым эти tv с необходимыми значениями присвоены. При группировке двух и более результатов подзапросов в таблицу попадают все товары с tv из первого подзапроса и из последующих. Но нам-то нужно, что бы все условия выполнялись, поэтому мы и выбираем только те товары, которые встречаются во временной таблице такое же количество раз, сколько и было подзапросов минус один.

А теперь код.

В том месте, где будет находиться поиск, вставляется форма, например такая:

<form action="ID_текущей_страницы" method="get">

<select name="tip_bluda">

<option value="">Тип блюда</option>

<option value="5">Супы</option>

<option value="16">Салаты</option>

<option value="6">Мясные блюда</option>

</select>

<select name="vid_kuhni">

<option value="">Вид кухни</option>

<option value="32">Русская</option>

<option value="35">Грузинская</option>

</select>

<select name="slojnost">

<option value="">Сложность</option>

<option value="1">Элементарно</option>

<option value="2">Легко</option>

<option value="3">Требует времени</option>

</select>

<input type="submit" value="Найти " />

</form>

Обязательно устанавливается method="get" – он нужен, что бы передавать выбранные значения. Name в select`те соответствует имени tv-параметра. Value в option значению, записанному в базе данных. На данном сайте в большинство tv параметров записываются ID страниц, к которым принадлежат товары, это нужно для сортировки. Если значения в базе хранятся на русском языке, то необходимо в сниппете будет присваивать им численные значения, из-за того, что значения на русском языке некорректно работают.

После формы пишем вызов сниппета: [ !filter! ]

И создаем сам спиппет с именем filter:

<?php

$output = '';

$filter = array();

$sl = 0;

if($_GET['slojnost'] == 1) $sl = 'Элементарно';

if($_GET['slojnost'] == 2) $sl = 'Легко';

if($_GET['slojnost'] == 3) $sl = 'Требует времени';

if($_GET['slojnost'] == 4) $sl = 'Нужно постараться ';

if($_GET['slojnost'] == 5) $sl = ‘Шедевр кулинарного искусства';

if(isset($_GET['tip_bluda']) && !is_array($_GET['tip_bluda']) && $_GET['tip_bluda'] != 0) $filter[] = '(SELECT contentid FROM modx_catalog_tmplvar_contentvalues WHERE value = "__'.$_GET['tip_bluda'].'")';

if(isset($_GET['vid_kuhni']) && !is_array($_GET['vid_kuhni']) && $_GET['vid_kuhni'] != 0) $filter[] = '(SELECT contentid FROM modx_catalog_tmplvar_contentvalues WHERE value = "__'.$_GET['vid_kuhni'].'")';

if(isset($_GET['slojnost']) && !is_array($_GET['slojnost']) && $_GET['slojnost'] != 0) $filter[] = '(SELECT contentid FROM modx_catalog_tmplvar_contentvalues WHERE value like "'.$sl.'")';

 

$params['parents'] = 'ID ресусрсов';

$params['tpl'] = 'имя чанка краткого описания товара';

$params['descTpl'] = 'имя чанка подробного описания товара';

$params['sqlFilter'] = '1';

$params['sortDir'] = 'desc';

$params['display'] = '20';

$params['noResult'] = '<p>Рецептов, соответствующих условиям поиска нет. Попробуйте задать более мягкие условия.</p>';

$filt = implode(' UNION ALL ',$filter);

$n = count($filter);

if ($n==0) $params['where'] = '';

if ($n==1) $params['where'] = "sc.id IN (SELECT contentid FROM ($filt) AS vremennaia GROUP BY contentid)";

if ($n>1) $params['where'] = "sc.id IN (SELECT contentid FROM ($filt) AS vremennaia GROUP BY contentid HAVING count(contentid)>($n-1))";

$output = $modx->runSnippet('catalogView',$params);

return $output;

?>

Теперь поподробнее о самом сниппете. В самом начале создается массив с параметрами вызова catalogView. Далее идет пример перевода текстовых значений в числовые. Назначается параметр, и при соотвествие одному из условий ему присваивается значение, по которому уже идет выборка из базы данных.

Теперь идет самая важная часть – если была передана переменная с помощью формы, то формируется подзапрос к базе данных. Здесь необходимо дописать все переменные, используемые в форме поиска. $_GET['tip_bluda'] – в скобках пишется имя tv параметра, которое совпадает с name select`а. В последнем условие, вместо выбора по tv параметру, происходит выбор по переменной, присвоенной нами вначале сниппета.

$params['parents'] = 'ID ресусрсов'; - перечисляются дополнительные параметры сниппета catalogView. В скобках название параметра, в кавычках напротив знака равно его значение.

$filt = implode(' UNION ALL ',$filter); - этой строкой все подзапросы объединяются в единую временную таблицу.

$n = count($filter); - подсчитывается количество подзапросов к базе данных.

if ($n==0) $params['where'] – определяется, сколько условий поиска было заданно, и формируется окончательный вызов сниппета catalogView. Если запросов более 1, то выбираются из временной таблицы значения, встречающиеся $n-1 раз.

Вот, в общем, и всё. Возможно, это не очень рационально, или некорректно. Но оно работает. Посмотрим, как будет себя вести при большом количестве товаров. Надеюсь, кому-нибудь поможет.

  • Портфолио
  • Услуги
  • Цены
  • Контакты
© 2009-2018 All Rights Reserved