Начну пожалуй с того, что этот скрипт я писал для сайта-каталога graon-stone.ru. Данный сайт - это каталог продукции компании, занимающейся изготовлением изделий из различных пород камней. Поэтому фильтрами были: тип камня, цвет камня, поверхность камня, ну и признак в наличии. Фильтры задаются tv-параметрами, всего их оказалось 4. В данной статье я расскажу вам, как самому реализовать фильтр для простого каталога с помощью MODx API и getResources.
Итак, начнем. Фильтр будет применяться (отправляться) с помощью GET формы на ту же страницу. Для страниц каталога камней и каждого типа камня я буду использовать один и тот же шаблон. В котором и будет вызываться наш сниппет.
Форма фильтра, как и его обработка будут происходить в одном сниппете. В данном случае я назвал его catalogFilter.
В сниппете сперва необходимо получить идентификатор страницы, это в дальнейшем поможет нам определить в каком уровне мы находимся, для применения необходимых "стандартных" фильтров. Это делается совсем просто. Вызовем метод модх resource get
$page_id = $modx->resource->get('id');
Далее нам необходимо сделать форму для фильтра. Как вы и поняли, она будет генерироваться внутри сниппета.
Повторюсь еще раз форму мы будем отправлять методом GET, дабы избежать вопросов о повторной отправке данных, что совсем не понравиться пользователю.
Первое, что мы будем использовать в фильтре это тип камня. В моем случае тип камня - это и есть категория каталога. Поэтому сперва мы получим все категории и разберем их форичем (foreach). А так же отметим, если данная запись есть в запросе, или же, если мы находимся в этой категории.
Данное условие будет отмечать выбранный фильтр. В данном примере 8 - это id верхнего уровня каталога. Разберем подробно: если значение данного параметра есть в GET-запросе ИЛИ если оно равно значению страницы, на которой мы находимся и при этом GET-запрос пустой и страница не равна 8, т.е. корневому каталогу, то отмечаем его как выбранный.
В данном случае, если был применен какой-то фильтр, то они отметятся в списке, если нет и мы находимся на страницы одной из категории, то отметиться та категория в которую мы зашли. В конце статьи мы еще раз вернямся к этому условию, что установить родителей для getResources.
if(in_array($value, $_GET['rock_type']) || ($page_id!=8 && !isset($_GET['rock_type']) && $page_id==$value )) echo "checked";
А это полная форма вывода фильтра с условием. Вначале мы получаем список всех категорий, а потом разбираем их и отмечаем выбранные фильтры.
//тип камня
$rock_type = $modx->getChildIds(8,1);
?>
Вид камня
foreach($rock_type as $key => $value)
{
?>
value=" echo trim($value); ?>">
echo $modx -> getObject('modResource', $value)->get("pagetitle"); ?>
}
?>
Далее мы сформируем оставшиеся фильтры. Цвет камня и поверхность камня. Заданы списком с одиночным выбором. В данном случае мы получаем все возможные варианты TV параметра и при формировании списка сравниваем их значения с массивом GET запроса.
//цвет камня
$tv_rock_color = $modx->getObject('modTemplateVar',array('name'=>'rockColor'));
$rock_color = $tv_rock_color->get('elements');
$rock_color = explode("||",$rock_color);
?>
Цвет
foreach($rock_color as $key => $value)
{
$color_val = explode("==",$value);
?>
value=" echo trim($color_val[1]); ?>"> echo trim($color_val[0]); ?>
}
?>
//поверхность камня
$tv_rock_surface = $modx->getObject('modTemplateVar',array('name'=>'rockSurface'));
$rock_surface = $tv_rock_surface->get('elements');
$rock_surface = explode("||",$rock_surface);
?>
Поверхность
foreach($rock_surface as $key => $value)
{
$surface_val = explode("==",$value);
?>
value=" echo trim($surface_val[1]); ?>"> echo trim($surface_val[0]); ?>
}
?>
А теперь сделаем фильтр по наличию, думаю тут все просто и объяснять не нужно.
value="1">В наличии
С формированием списка параметров фильтра мы разобрались, теперь когда список сформирован мы можем выводить записи с помощью getResources отфильтрованные нашим фильтром. Сформируем строку TV фильтра из полученных параметров GET запроса. Именно сформируем, т.к. tvFilters принимают только строку с указанием условий. Подробнее об условиях параметра TV-фильтров тут: документация getResources.
//фильтр по цвету
$rockColor=="";
foreach($_GET['rock_color'] as $key => $value)
{
if($_GET['in_stock']==1) $rockColor.="instock==1,";
/*
если установлено в наличии, то добавляем (instock==1,) -
это означает, что запись должна быть в наличии и определенного цвета.
Далее действуем таким же способом для поверхности.
*/
$rockColor.="rockColor==%" . $value . "%||";
}
$rockSurface=="";
foreach($_GET['rock_surface'] as $key => $value)
{
if($_GET['in_stock']==1) $rockSurface.="instock==1,";
$rockSurface.="rockSurface==%" . $value . "%||";
}
$filter .= $rockColor . $rockSurface;
//скеиваем фильтры
//если фильтруем по цвету или покрытию, то урезаем 2 последних символа, т.е. логическое или ||
if($rockColor!="" || $rockSurface!="")
{
$filter = substr($filter, 0, -2);
}
//иначе, если указан фильтр по наличию, прописываем этот параметр.
else
{
if($_GET['in_stock']==1) $filter.="instock==1";
}
Далее все просто, вызываем сниппет getResources с наборо параметров $settings. Так же мы проверим на выбранность категории (типа камня) и установим значение, если мы пришли на страницу категории.
$settings = array(
'elementClass'=>'modSnippet',
'element'=>'getResources',
'tpl'=>'rocksTpl',
'includeTVs'=>'1',
'processTVs'=>'1',
'includeContent'=>'1',
'hideContainers' =>'1',
'limit' => '9',
'pageLimit'=>'6',
'pageFirstTpl'=>'',
'pageLastTpl'=>'',
'pageActiveTpl'=>'',
'sortby' => '{"createdon":"ASC"}',
'tvFilters'=>$filter
);
if($page_id!=8 && !isset($_GET['rock_type']))
{
$settings['parents']=$page_id;
//устанавливаем категорию, если ничего не выбрано и мы не в каталоге
}
elseif(isset($_GET['rock_type']))
{
//склеиваем список категорий для фильтрации, если они выбраны, при этом в TV параметре должен быть выбраны параметры вывода "Строка".
$types = implode(",",$_GET['rock_type']);
$settings['parents']=$types;
}
else
{
//Иначе выводим товары вех категорий
$settings['parents']=8;
}
$output = $modx->runSnippet('getPage', $settings);
echo $output;
$modx->getPlaceholder('page.nav');
Возможно это не самый простой вариант как можно организовать фильтрацию для каталога, но один из первых, который пришел мне в голову. Он прост в реализации и не требует затрат на выполнение. Но я готов поделитья с вами своими начинаниями в оcвоении MODx Revolution.