Матвей Земсков

Заметки веб-мастера

Воскресенье, 26 января 2014 10:01

Создаем свой фильтр на сайте под управлением «1С-Битрикс»

Оцените материал
(14 голосов)

При разработке одного сайта, передо мной встала следующая задача: нужно было создать компонент для быстрого подбора элементов каталога и разместить его на каждой странице сайта. Результат его работы должен был отображаться на отдельной странице. Немного подумав, я понял, что этот компонент очень похож на стандартные фильтры, реализованные в системе «1С-Битрикс», но из-за особенностей их работы они мне не подходили. В этой статье я опишу процесс поиска решения этой задачи. Возможно, он будет полезен другим разработчикам, если они столкнуться с аналогичным заданием. Все изыскания я проводил на демо-версии системы. При установке ее на локальный веб-сервер, я выбрал вариант «для разработчиков». Сразу хочу предупредить читателя, что мое решение не является идеальным, может быть вы сможете придумать что-то лучшее. Возможно, статья покажется вам сложной для понимания, поэтому читайте внимательней, я постараюсь объяснить здесь тонкости разработки компонента как можно проще.

Зачем нужен свой фильтр и почему бы не использовать стандартные?

В системе «1С-Битрикс» существует 2 компонента с функционалом фильтра – это «Умный фильтр» (bitrix:catalog.smart.filter) и «Фильтр по элементам» (bitrix:catalog.filter). По сути это просто HTML-формы с полями, в которых указаны критерии для фильтрации элементов. «Умный фильтр» обычно размещается в комплексном компоненте «Каталог», а именно на страницах со списком элементов раздела. Если разместить на странице сайта только этот компонент, корректно работать он не будет, потому что в его настройках нельзя указать страницу с компонентом, который будет фильтровать элементы и показывать результаты. То же самое касается фильтра по элементам. Его также нужно размещать на страницах комплексного компонента «Каталог». Также у этого фильтра нет никаких настроек, касающихся типа полей, которые будут использованы в HTML-форме фильтра. На рисунке можно увидеть стандартные HTML-формы фильтров в Битриксе и то, что нужно было мне.

Фильтры в 1С-Битрикс

Конечно, можно было бы попытаться настроить под себя имеющиеся фильтры, но я решил не «заморачиваться» с настройками, потому что был не уверен в результате, а зря тратить время мне не хотелось. В итоге я решил написать свой компонент. Я назвал его elfilter и разместил в папке /bitrix/components/mattweb/. Далее в тексте статьи я буду называть его mattweb:elfilter.

Как все это работает

Как я писал выше фильтр – это по сути просто HTML-форма, в полях которой собираются уникальные значения свойств элементов инфоблока. В форме фильтра используются поля различного типа. Тип полей формы (например: text, select, checkbox) зависит от типа свойства элемента инфоблока.

При нажатии кнопки «Фильтр» данные методом POST передаются странице, на которой расположен компонент, выводящий список элементов инфоблока. Этот компонент и будет показывать результаты работы фильтра.

К URL страницы добавляется GET-параметр use_filter=y, который указывает, что фильтр активен. Параметры для фильтрации элементов сохраняются в пользовательских параметрах (elfilter и curFilterParams). Это нужно для обеспечения корректной работы фильтра, если отфильтрованные элементы не помещаются на одну страницу.

Для показа отфильтрованных элементов я решил использовать компонент bitrix:news.list, указав в параметрах его вызова фильтр ($arParams["FILTER_NAME"] => "arrElementsFilter"). В массив $arrElementsFilter я поместил данные, переданные из формы, предварительно обработал их и привел в определенный формат.

В принципе оба компонента (фильтр и список элементов) можно разместить на одной странице.

Ниже приведена схема работы компонента mattweb:elfilter.

Схема работы фильтра mattweb:elfilter

Параметры компонента mattweb:elfilter

Как известно, у любого компонента в системе «1С-Битрикс» есть определенный набор папок и файлов из которых он, собственно, и состоит. Но о них я напишу немного позже, а сейчас начну с описания параметров моего компонента. Параметры компонента в системе «1С-Битрикс» хранятся в файле .parameters.php в папке компонента в массиве $arComponentParameters. Этот массив имеет определенную структуру и описывает параметры компонента. Параметры моего компонента немного «выбиваются» из этой структуры, поэтому я этот файл создавать не буду, благо он необязательный. Это никак не отобразиться на работе компонента, так как параметры в него будут передаваться при вызове компонента на страницах сайта. Мне нужно чтобы компонент присутствовал на каждой странице, поэтому я разместил его вызов в файле шаблона сайта. Вот так выглядит код вызова моего компонента.

PHP

$APPLICATION->IncludeComponent("mattweb:elfilter", ".default", Array(
    "IBLOCK_TYPE" => "books",    // Тип информационного блока (используется только для проверки)
    "IBLOCK_ID" => "6",  // Код информационного блока
    "ACTION_URL" => " /filtered.php",
    "USE_SECTION_FILTER" => "Y", // Фильтровать по разделам	
    "ARR_PROPERTIES" => Array(
        "AUTHORS" => Array(
            "PROP_NAME" => "Автор(ы)",
            "PROP_ID" => "AUTHORS",
            "PROP_TYPE" => "E",
            "LNKD_IBLOCK_ID" => "5",         
            "FLTFIELD_TYPE" => "ISM"
        ),
        "PUBLISHER" => Array(
            "PROP_NAME" => "Издатель",
            "PROP_ID" => "PUBLISHER",
            "PROP_TYPE" => "S",          
            "FLTFIELD_TYPE" => "IS"         
        ),
        "BK_PRICE" => Array(
            "PROP_NAME" => "Цена",
            "PROP_ID" => "BK_PRICE",
            "PROP_TYPE" => "N",          
            "FLTFIELD_TYPE" => "ISL"
        ),
        "PAGES" => Array(
            "PROP_NAME" => "Число страниц",
            "PROP_ID" => "PAGES",
            "PROP_TYPE" => "N",
            "FLTFIELD_TYPE" => "ISR",
            "RNG_PARTS" => "5"
        ),
        "RENT_SELL" => Array(
            "PROP_NAME" => "Прокат/Продажа",
            "PROP_ID" => "RENT_SELL",
            "PROP_TYPE" => "L",
            "FLTFIELD_TYPE" => "IR"
        ),
        "IMAGES_SECTION" => Array(
            "PROP_NAME" => "Иллюстрации",
            "PROP_ID" => "IMAGES_SECTION",
            "PROP_TYPE" => "G",
            "FLTFIELD_TYPE" => "ISM"
        ),
    ),
    ),
  false
); 

Ну вот, теперь самое время описать все элементы массива $arParams.

  • IBLOCK_ID – идентификатор инфоблока, элементы которого будут фильтроваться;
  • ACTION_URL – URL страницы, на которую будут отправляться параметры фильтра;
  • USE_SECTION_FILTER - включить возможность фильтрации элементов по разделам (секциям)
  • ARR_PROPERTIES – массив с данными о свойствах элементов и соответствующих им полях в форме фильтра. Каждый элемент массива описывает поле в фильтре. Важно: для корректной работы компонента имена ключей массива ARR_PROPERTIES должны соответствовать именам свойств в инфоблоке;
  • PROP_NAME – текст подписи к полю в форме (название поля). Равен названию свойства в инфоблоке;
  • PROP_ID – идентификатор свойства в инфоблоке;
  • PROP_TYPE – тип свойства в инфоблоке (S - строка, N - число, F - файл, L - список, E - привязка к элементам, G - привязка к группам);
  • FLTFIELD_TYPE – тип поля в форме фильтра;

Параметр «тип поля в форме фильтра» был придуман для того, чтобы иметь возможность в зависимости от его значения размещать в форме различные типы HTML-элементы (например, текстовые поля, списки, списки с множественным выбором, слайдеры, чекбоксы и тп). У этого параметра есть определенный список значений.

  • IT – текстовое поле;
  • IS – выпадающий список (select);
  • ISM – выпадающий список, с возможностью выбора нескольких элементов;
  • ISL – слайдер (реализован на основе jQuery noUiSlider);
  • ISR – выпадающий список, значения которого представляют равные промежутки (например, 1-10, 11-20, 21-30 и тд);
  • ICH – флажки (checkbox);
  • IR – флажки (radio);

Файлы компонента

Файлы компонента mattweb:elfilter

Мой компонент состоит из следующих файлов:

В папке js/ находятся файлы плагина jQuery noUiSlider, который необходим мне для размещения слайдера в форме.

Папка templates/.default/ содержит шаблон компонента. В ней 3 файла – сам шаблон (template.php), файл стилей (style.css) и файл component_epilog.php, который служит для подключения плагина jQuery noUiSlider.

В папке компонента находится файл component.php, который содержит весь код моего компонента. Вообще-то в этой папке еще могут быть 2 файла - .parameters.php, о котором я писал выше и .description.php – в котором хранится массив с описанием компонента. В моем случае эти файлы мне не нужны, в том числе, потому что я не собираюсь размещать компонент на страницах сайта с помощью визуального редактора.

Код компонента

Код компонента, находящийся в файле component.php разделен на блоки. По логике своей работы они аналогичны, поэтому я расскажу только про один блок, а с остальными можно ознакомиться заглянув в код компонента. Ничего сложного в нем нет. Но для начала нужно обработать входные параметры, передаваемые в компонент.

PHP

if(!CModule::IncludeModule('iblock')){
	showError("Не установлен модуль Инфоблоки");
}

global $USER;

$arParams["IBLOCK_ID"] = intVal($arParams["IBLOCK_ID"]);
$arParams["ACTION_URL"] = trim($arParams["ACTION_URL"])."?use_filter=y";
$arResult = Array();

В самом начале файла подключаем модуль «Информационные блоки». После этого нам становятся доступны все методы его классов. Преобразуем идентификатор инфоблока в число и избавляемся от лишних пробелов в URL страницы с компонентом, выводящим результаты работы фильтра. Помните, я писал о ней выше? Да-да, той самой с компонентом bitrix:news.list.

Затем создаем пустой массив $arResult для хранения результатов работы компонента. Результатом работы компонента станет HTML-код отдельных полей формы фильтра, который будет «превращаться» в форму в шаблоне компонента. Итак, если в параметрах переданы какие-нибудь данные о свойствах и полях, начинаем обходить их в цикле и в зависимости от типа свойств и типа полей, обрабатываем их и сохраняем результат работы в массиве $arResult["FIELDS"], каждый элемент отдельно.

Если пользователь выбрал параметры для фильтрации и отправил данные из формы - обрабатываем данные и сохраняем их для дальнейшего использования. На случай если в отфильтрованных результатах будет несколько страниц.

Храниться эти данные будут в параметрах пользователя.

PHP

if($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["filter_send"])){
	$arrElementsFilter = Array();
	
	foreach($_POST as $key=>$val){
		if($key == "SECTIONS" && !in_array("-", $_POST["SECTIONS"])){
			// фильтр по секциям (массив)
            $arrElementsFilter["SECTION_ID"] = $_POST["SECTIONS"];
		}
		else if((strpos($key, "PROPERTY_") !== false && !is_array($val) && $val != "-" && $val != "") || (strpos($key, "PROPERTY_") !== false && is_array($val) && !in_array("-", $val))){
			// фильтр по свойствам
			$filterPropName = substr_replace($key, '', 0, strlen("PROPERTY_"));
			if(array_key_exists($filterPropName, $arParams["ARR_PROPERTIES"])){
				// получаем тип поля фильтра
				$filterFieldType = $arParams["ARR_PROPERTIES"][$filterPropName]["FLTFIELD_TYPE"];
				
				switch ($filterFieldType){
					case "IT":
						$arrElementsFilter["$key"] = "%".$val."%";
					break;
					case "IS":
						$arrElementsFilter["$key"] = $val;						
					break;
					case "ISM":
						if(is_array($val) && count($val) > 0){
							$arrElementsFilter[] = Array(
								"LOGIC" => "OR",                 
								array("$key" => $val)
							);
						}
					break;
					case "ISL":
						$rngpattern = "/^[0-9]+\-[0-9]+$/";
						if(preg_match($rngpattern, $val)){
							$arrVals = explode("-",$val);
							$arrElementsFilter["><$key"] = $arrVals;
						}
					break;
					case "ISR":
						$rngpattern = "/^[0-9]+\-[0-9]+$/";
						if(preg_match($rngpattern, $val)){
							$arrVals = explode("-",$val);
							$arrElementsFilter["><$key"] = $arrVals;
						}
					break;
					case "ICH":
						if(is_array($val) && count($val) > 0){
							$arrElementsFilter[] = Array(
								"LOGIC" => "OR",                 
								array("$key" => $val)
							);
						}
					break;
					case "IR":
						$arrElementsFilter["$key"] = $val;
					break;
				}
				
			}
		}		
	}
	
	$USER->SetParam('elfilter', $arrElementsFilter);
	$USER->SetParam('curFilterParams', $_POST);
}

if(isset($_GET["use_filter"]) && $_GET["use_filter"] == "y"){
	$arrFilterCurParams = $USER->GetParam('curFilterParams');
}

Предварительно очищаем параметры пользователя от предыдущих параметров фильтра. Делаем это в обоих случаях и при получении параметров для фильтра из формы, и при отключении фильтра - «очистке» элементов от фильтра.

PHP

if($_SERVER["REQUEST_METHOD"] == "POST" && (isset($_POST["filter_send"]) || isset($_POST["filter_reset"]))){
	$USER->SetParam('elfilter', '');
	$USER->SetParam('curFilterParams', '');
}

Переходим к описанию блока с кодом. Для примера я взял блок, работающий с текстовым свойством инфоблока.

PHP

…
elseif($arProp["PROP_TYPE"] == "S")
		{
			//строка
			
			$arpropvals = Array();
			
			$propcd = "PROPERTY_".strtoupper($arProp["PROP_ID"]);
			$arSelect = Array("ID", $propcd);
			
			$arFilter = Array(
				"IBLOCK_ID" => $arParams["IBLOCK_ID"], 
				"INCLUDE_SUBSECTION" => "Y"
			);

			$res = CIBlockElement::GetList(Array(), $arFilter, false, false, $arSelect);
			while($ob = $res->GetNextElement()){
				$arFlds = $ob->GetFields();
				if(!in_array($arFlds[$propcd."_VALUE"], $arpropvals)){
					$arpropvals[$arFlds[$propcd."_VALUE_ID"]] = $arFlds[$propcd."_VALUE"];				
				}				
			}
			if(count($arpropvals) > 0)
			{
				asort($arpropvals);
				if($arProp["FLTFIELD_TYPE"] == "IS" || $arProp["FLTFIELD_TYPE"] == "ISM"){
					//select
					$fld_html = '<select name="PROPERTY_'.$arProp["PROP_ID"];
					if($arProp["FLTFIELD_TYPE"] == "ISM") $fld_html .= '[]" multiple = "multiple" size="5">';
					if($arProp["FLTFIELD_TYPE"] == "IS") {
						$fld_html .= '">';						
					}
					$fld_html .= '<option value="-">-</option>';
					foreach($arpropvals as $key => $value){
						if(empty($key) || empty($value)) continue;
						if(array_key_exists("PROPERTY_".$arProp["PROP_ID"], $arrFilterCurParams) && $arrFilterCurParams["PROPERTY_".$arProp["PROP_ID"]] == $value)
						{
							$fld_html .= '<option value="'.$value.'" selected="selected">'.$value.'</option>';
						}
						else
						{
							$fld_html .= '<option value="'.$value.'">'.$value.'</option>';
						}						
					}
					$fld_html .= '</select>';
				}
				else{
					// input type="text"
					$fld_html = '<input type="text" name="PROPERTY_'.$arProp["PROP_ID"].'" id="fld_'.$arProp["PROP_ID"].'"/>';
				}			
								
				$arResult["FIELDS"][] = Array(
					"FLDNAME" => $arProp["PROP_NAME"],
					"PROPTYPE" => $arProp["PROP_TYPE"],
					"FIELDTYPE" => $arProp["FLTFIELD_TYPE"],
					"VALUE" => $arpropvals,
					"FLD_HTML" => $fld_html
				);
			}
			else
			{
				$arResult["ERRORS"][] = "У свойства ".$arProp["PROP_ID"]." нет значений для фильтра";
			}			
		}
…

Итак, сначала получаем все значения свойства элементов инфоблока и сохраняем их в массив с именем $arpropvals. Ключами у элементов массива будут идентификаторы элементов инфоблока. Если значения есть и массив непустой, сортируем его, сохраняя ключи. Затем в зависимости от параметра типа поля (IS или ISM) в форме формируем HTML-код и сохраняем результат в массиве $arResult["FIELDS"]. Как видите, ничего сложного нет. Аналогично устроены и другие блоки кода, обрабатывающие другие типы полей.

Чтобы понять, как формируется HTML-код чекбоксов и радио-кнопок, ознакомьтесь с блоком кода, обрабатывающим свойства типа «Список».

Подключение плагина jQuery noUiSlider для создания слайдера в форме

В блоке кода, работающего в полем типа слайдер, формируется HTML-код, необходимый для корректной работы плагина jQuery noUiSlider. Подключение плагина происходит в файле component_epilog.php в обход кэширования.

Подробнее ознакомиться с кодом можно в файле component.php (строки 347-383).

Вызов плагина производится в шаблоне компонента, параметры берутся из архива $arResult.

Настройки инфоблока для демонстрации работы компонента

Для демонстрации работы компонента в демо-версии сайта, необходимо добавить новые свойства в информационный блок «Книги» (Тип – «Каталог книг»). Это нужно для большей наглядности. На рисунке ниже показаны эти свойства, их имена и типы.

Настройки свойств инфоблока

Значения свойства BK_PRICE, являются ценами товаров каталога. Тип - «Число».

Значения свойства RENT_SELL, являющиеся элементами списка, будут следующие: первый элемент - «Продажа», второй элемент списка - «Прокат». Выбрать можно только один элемент.

Значения свойства IMAGES_SECTION, берутся из инфоблока «Фотографии» (тип - «Фотогалерея»).

Скачать файлы для импорта в информационный блок «Книги»

После создания свойств, вы можете импортировать данные из .CSV-файла в информационный блок или заполнить их вручную.

Размещение компонента на странице сайта

Переходим к заключительной части статьи, а именно, к размещению компонента на странице. Немного отступлю от выше приведенной схемы и размещу оба компонента (и фильтр и список результатов) на одной странице (filtered.php). По логике работы компонента, при активном фильтре в полях формы должны находиться выбранные ранее значения. Создайте страницу с именем filtered.php в корне демо-сайта и разместите там следующий код:

PHP

<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("фильтр");
?>
<?
// компонент фильтр
$APPLICATION->IncludeComponent("mattweb:elfilter", ".default", Array(
    "IBLOCK_TYPE" => "books",    // Тип информационного блока (используется только для проверки)
    "IBLOCK_ID" => "6",  // Код информационного блока
    "ACTION_URL" => " /filtered.php",
    "USE_SECTION_FILTER" => "Y", // Фильтровать по разделам	
    "ARR_PROPERTIES" => Array(
        "AUTHORS" => Array(
            "PROP_NAME" => "Автор(ы)",
            "PROP_ID" => "AUTHORS",
            "PROP_TYPE" => "E",
            "LNKD_IBLOCK_ID" => "5",         
            "FLTFIELD_TYPE" => "ISM"
        ),
        "PUBLISHER" => Array(
            "PROP_NAME" => "Издатель",
            "PROP_ID" => "PUBLISHER",
            "PROP_TYPE" => "S",          
            "FLTFIELD_TYPE" => "IS"         
        ),
        "BK_PRICE" => Array(
            "PROP_NAME" => "Цена",
            "PROP_ID" => "BK_PRICE",
            "PROP_TYPE" => "N",          
            "FLTFIELD_TYPE" => "ISL"
        ),
        "PAGES" => Array(
            "PROP_NAME" => "Число страниц",
            "PROP_ID" => "PAGES",
            "PROP_TYPE" => "N",
            "FLTFIELD_TYPE" => "ISR",
            "RNG_PARTS" => "5"
        ),
        "RENT_SELL" => Array(
            "PROP_NAME" => "Прокат/Продажа",
            "PROP_ID" => "RENT_SELL",
            "PROP_TYPE" => "L",
            "FLTFIELD_TYPE" => "IR"
        ),
        "IMAGES_SECTION" => Array(
            "PROP_NAME" => "Иллюстрации",
            "PROP_ID" => "IMAGES_SECTION",
            "PROP_TYPE" => "G",
            "FLTFIELD_TYPE" => "ISM"
        ),
    ),
    ),
  false
); 

$arrElementsFilter = (isset($_GET['use_filter'])) ? $USER->GetParam('elfilter') : "";
$pagerBaseLink = (isset($_GET['use_filter'])) ? $APPLICATION->GetCurPage()."?use_filter=y" : "";

if(!isset($_GET['use_filter'])){
	$USER->SetParam('elfilter', '');
}

$APPLICATION->IncludeComponent("bitrix:news.list", "filtered", array(
		"IBLOCK_TYPE" => "books",
		"IBLOCK_ID" => "6",
		"NEWS_COUNT" => "5",
		"SORT_BY1" => "ACTIVE_FROM",
		"SORT_ORDER1" => "DESC",
		"SORT_BY2" => "SORT",
		"SORT_ORDER2" => "ASC",
		"FILTER_NAME" => "arrElementsFilter",
		"FIELD_CODE" => array(
			0 => "",
			1 => "",
		),
		"PROPERTY_CODE" => array(
			0 => "PAGES",
			1 => "PUBLISHER",
			2 => "RENT_SELL",
			3 => "BK_PRICE",
			4 => "IMAGES_SECTION",
			5 => "AUTHORS",
			6 => "",
		),
		"CHECK_DATES" => "Y",
		"DETAIL_URL" => "",
		"AJAX_MODE" => "N",
		"AJAX_OPTION_JUMP" => "N",
		"AJAX_OPTION_STYLE" => "Y",
		"AJAX_OPTION_HISTORY" => "N",
		"CACHE_TYPE" => "N",
		"CACHE_TIME" => "36000000",
		"CACHE_FILTER" => "N",
		"CACHE_GROUPS" => "Y",
		"PREVIEW_TRUNCATE_LEN" => "",
		"ACTIVE_DATE_FORMAT" => "d.m.Y",
		"SET_TITLE" => "Y",
		"SET_STATUS_404" => "N",
		"INCLUDE_IBLOCK_INTO_CHAIN" => "Y",
		"ADD_SECTIONS_CHAIN" => "Y",
		"HIDE_LINK_WHEN_NO_DETAIL" => "N",
		"PARENT_SECTION" => "",
		"PARENT_SECTION_CODE" => "",
		"INCLUDE_SUBSECTIONS" => "Y",
		"PAGER_TEMPLATE" => ".default",
		"DISPLAY_TOP_PAGER" => "N",
		"DISPLAY_BOTTOM_PAGER" => "Y",
		"PAGER_BASE_LINK_ENABLE" => "Y",
		"PAGER_BASE_LINK" => $pagerBaseLink, 	
		"PAGER_TITLE" => "Элементы",
		"PAGER_SHOW_ALWAYS" => "Y",
		"PAGER_DESC_NUMBERING" => "N",
		"PAGER_DESC_NUMBERING_CACHE_TIME" => "36000",
		"PAGER_SHOW_ALL" => "Y",
		"DISPLAY_DATE" => "Y",
		"DISPLAY_NAME" => "Y",
		"DISPLAY_PICTURE" => "Y",
		"DISPLAY_PREVIEW_TEXT" => "Y",
		"AJAX_OPTION_ADDITIONAL" => ""
		),
		false
	);
?>
<?require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");?>

Как вы видите, на странице подключаются 2 компонента: mattweb.elfilter (фильтр) и bitrix:news.list (список новостей).

Если фильтр активен, получаем значения для фильтрации элементов из параметра пользователя elfilter и передаем этот массив в компонент bitrix:news.list. Кроме того, формируем правильные ссылки для постраничной навигации.

Иначе очищаем параметр пользователя elfilter и показываем полный список элементов.

Обращаю ваше внимание, что значения параметров в вызове компонентов указаны для демо-версии системы.

Если все сделано правильно, то на указанная страница будет выглядеть так, как на рисунке ниже.

Страница с компонентами

Добавляем возможность фильтровать по разделам (добавлено 26.08.2015)

В компоненте добавлена возможность фильтровать элементы инфоблока по разделам. Для этого я немного изменил файлы компонента. В приведенных выше примерах кода эти изменения учтены.

Также необходимо добавить в файл component.php следующий код:

PHP

$arResult["FIELDS"] = Array();

// фильтр по секциям
if(isset($arParams["USE_SECTION_FILTER"]) && $arParams["USE_SECTION_FILTER"] == "Y"){	
	$arSectFilter = Array(
		"IBLOCK_ID" => $arParams["IBLOCK_ID"],
		"GLOBAL_ACTIVE" => "Y"
	);
	// Если у инфоблока есть секции
	if(CIBlockSection::GetCount($arSectFilter) > 0){
		$arrSections = Array();
		$dbSectList = CIBlockSection::GetList(Array("SORT" => "ASC"), $arSectFilter, false, Array("ID","NAME"));
		
		// получаем список секций инфоблока (массив "ИД_РАЗДЕЛА" => "Название раздела")
		while($tmpSectArr = $dbSectList->Fetch()){
			$arrSections[$tmpSectArr["ID"]] = $tmpSectArr["NAME"];
		}
		
		// Формируем html на основе данных и добавляем его в $arResult["FIELDS"]
		$fld_html = '<select name="SECTIONS[]" multiple = "multiple" size="5">';
		$fld_html .= '<option value="-">-</option>';
		foreach($arrSections as $key => $value){
			if(array_key_exists("SECTIONS", $arrFilterCurParams) && in_array($key, $arrFilterCurParams["SECTIONS"]))
			{
				$fld_html .= '<option value="'.$key.'" selected="selected">'.$value.'</option>';
			}
			else{
				$fld_html .= '<option value="'.$key.'">'.$value.'</option>';
			}			
		}
		$fld_html .= '</select>';
		
		$arResult["FIELDS"][] = Array(
			"FLDNAME" => "Разделы",
			"FIELDTYPE" => "ISM",
			"VALUE" => $arrSections,
			"FLD_HTML" => $fld_html
		);		
	}
}

Этот код вставляется между следующими строками:

PHP

…
// URL для отправки формы
$arResult["ACTION_URL"] = $arParams["ACTION_URL"];
/* 
 сюда вставляется приведенный выше код
 причем строку $arResult["FIELDS"] = Array();
 нужно перенести сюда из условного блока с проверкой (count($arParams["ARR_PROPERTIES"]) > 0)
*/
if(count($arParams["ARR_PROPERTIES"]) > 0)
…

В результате этих действий в фильтре добавляется список с возможность выбора нескольких категорий для фильтрации элементов инфоблока.

Поле для фильтрации по категориям

Обновление и доработки в компоненте mattweb.elfilter (добавлено 11.01.2016)

  • Добавлена возможность использования в фильтре чекбоксов (input type="checkbox") и радио-кнопок (input type="radio") для свойств типа «Список» (L);
  • Добавлена возможность выбора нескольких элементов из списка для свойств типа «Привязка к группам» (G);
  • У всех выпадающих списков в фильтре добавлена возможность выбора пустых значений;
  • Кнопка «Очистить» в форме фильтра теперь отключает фильтр. При клике по ней, страница обновляется и на ней показываются все элементы.
  • Исправлена ошибка: постраничная навигация при активном фильтре работала некорректно.
  • Исправлена ошибка: при использовании постраничной навигации при активном фильтре в форме не выделялись значения по которым происходила фильтрация.

Использование фильтра mattweb.elfilter в комплексном компоненте (добавлено 02.07.2016)

Добавлена возможность использования фильтра внутри комплексного компонента. Проверено на компоненте «Каталог» (bitrix:catalog) тестовой версии CMS(редакция «Стандарт»).

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

Я заменил вызов «умного» фильтра в файле section_vertical.php шаблона компонента «Каталог» (bitrix:catalog) своим.

Дефолтный шаблон компонента «Каталог» (bitrix:catalog) я предварительно скопировал в папку /bitrix/templates/.default/components/bitrix/catalog/.default/

Вы можете скачать измененные файлы для ознакомления.

Пример вызова компонента в файле section_vertical.php шаблона комплексного компонента «Каталог» (bitrix:catalog)

PHP

<?
	// компонент фильтр mattweb:elfilter
	$APPLICATION->IncludeComponent("mattweb:elfilter", ".default", Array(
		"IBLOCK_TYPE" => $arParams["IBLOCK_TYPE"], // Тип информационного блока (используется только для проверки)
		"IBLOCK_ID" => $arParams["IBLOCK_ID"],  // Код информационного блока
		"ACTION_URL" => "", // в случае комплексного компонента оставляем параметр пустым
		"USE_SECTION_FILTER" => "", // в случае комплексного компонента оставляем параметр пустым,
		"SECTION_ID" => $arCurSection['ID'], // добавляем новый параметр для комплексного компонента
		"ARR_PROPERTIES" => $arParams["ARR_PROPERTIES"]
		),
	  false
);?>

В указанном файле значения параметров берутся из файла, где вызывается комплексный компонент «Каталог» (bitrix:catalog).

В демо-версии это файл /e-store/books/index.php. В нем параметры компонента добавлены в код вызова комплексного компонента.

Они выглядят аналогично как в вызове простого компонента (см. пример в статье выше)

Для ознакомления вы можете скачать архив с компонентом. Чтобы установить компонент разархивируйте загруженный архив в папку /bitrix/components/.

Также вы можете скачать архив с шаблоном (filtered) компонента bitrix:news.list и страницу filtered.php.

Прочитано 36708 раз
Добавить комментарий

Комментарии   

 
0 # damon 10.07.2014 13:23
небольшая ошибочка в компоненте со списком результатов, имя фильтра в кавычках необходимо написать без пробелов
"FILTER_NAME" => "arrElementsFilter"
а то если с пробелами, то не обрабатываются значения из фильтра
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Матвей 14.07.2014 10:57
Спасибо, что нашли неточность - она появилась по всей видимости при вставке кода в статью. Все поправил.
Ответить | Ответить с цитатой | Цитировать
 
 
+2 # Тиим 25.08.2014 03:46
Читаю статью и мне все больше нравится! Отлично.
Сейчас делаю немного другой вариант фильтра. Может подскажете как можно вывести товары имея уже определенные значения свойств.
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Матвей 26.08.2014 13:23
Спасибо
Ответить | Ответить с цитатой | Цитировать
 
 
+1 # Андрей 19.03.2015 11:44
Здравствуйте, Матвей!
В коде компонента не нашел обработки типа поля в форме ICH - checkbox, IR - radio button :cry:

А жаль, сам компонент понравился :lol:
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 13.04.2015 16:23
Да, Андрей, я не стал обрабатывать все типы полей. Просто для той задачи это было не нужно. Но при желании можно расширить компонент, чтобы он обрабатывал эти указанные вами типы полей.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Юлия 10.04.2015 09:13
Прекрасный фильтр, но у меня почему-то очистка не работает (не чистит, не перегружает страницу). Подскажите, что делать
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 13.04.2015 16:49
Юлия, сложно сказать не видя вашего кода…Возможно вы где-то в настройках неверно указали что-то.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Дмитрий 19.05.2015 09:31
У меня тоже не работает ваша кнопка reset.
Вроде бы она находиться в форме и все правильно, но почемо ноль реакции на нее.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 19.05.2015 17:04
Дмитрий, эта кнопка предназначена для очистки полей формы, а не результата работы фильтра. Это стандартная возможность браузера, поэтому никакой обработчик не нужен. А кнопка для очистки результатов работы фильтра здесь не предусмотрена. В принципе это можно реализовать, функционал полезный получится.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Andrey 08.05.2015 16:06
Добрый день! Установил компонент как написано, но он не появляется в списке компонентов :oops:
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 14.05.2015 16:56
А он и не должен там появляться. Чтобы вызвать компонент на странице, пожалуйста, воспользуйтесь кодом, представленным выше
Ответить | Ответить с цитатой | Цитировать
 
 
0 # kostey 31.07.2015 12:46
Добрый день.
Будет-ли работать такой фильтр в каталоге с категориями?
Спасибо.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 26.08.2015 09:56
Добрый день! Да, категории этому фильтру не помеха. Кроме того, добавлена возможность фильтровать элементы по категориям.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Андрей 24.08.2015 15:59
Установил, Отличный компонент. Но есть один моментик, после фильтрации при активном фильтре в полях формы нет выбранных ранее значений. Хотя сам фильтр отлично работает.. Помогите разобраться
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 25.08.2015 11:26
Андрей, такая возможность в этом компоненте предусмотрена. Правда есть момент: это будет работать в том случае, если фильтр и компонент, который показывает результаты, находятся на одной странице.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Александр 04.03.2016 19:05
Матвей, классный фильтр получился, его немного причесать и в маркетплейс.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 12.03.2016 10:35
Спасибо, Александр!
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Андрей 13.06.2016 17:29
можно ли данный фильтр переделать под комплексный компонент catalog?
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 17.06.2016 15:55
Андрей, при желании это можно сделать. Ведь комплексный компонент состоит из простых, которые используются в примере из статьи. Однако нужно учитывать то, что я использую bitrix:news.list, а в каталоге применяется bitrix:catalog.section. Но думаю большой разницы нет, потому что в этот компонент также можно передавать параметры. Так что думаю, ваша задача решаема.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Наталья 28.06.2016 15:12
Добрый день. Вопрос такой, если нет результатов выборки, то хотелось бы, чтобы на странице появлялась фраза типа "По вашему запросу ничего не нашлось." Скажите пожалуйста, где вписать подобную фразу. Спасибо.
Ответить | Ответить с цитатой | Цитировать
 
 
0 # Матвей 02.07.2016 11:43
Добрый день, Наталья! Эту фразу нужно добавить в шаблон компонента, отображающего результаты работы фильтра. В нашем случае это шаблон 'filtered' компонента bitrix:news.list.
В самом начале файла нужно проверить количество элементов в массиве $arResult и существование переменной $_GET['use_filter'] и если массив пуст, а переменная существует, то вывести сообщение о том, что ничего не нашлось.
Ответить | Ответить с цитатой | Цитировать
 
Мои услуги

Предлагаю следующие услуги:

  • Верстка шаблона сайта из дизайн-макета для CMS «1С-Битрикс Управление сайтом» и CMS “Joomla”
  • Создание форм различной сложности (обратная связь, анкеты и тп) для указанных CMS
  • Настройка и кастомизация компонентов и модулей для указанных CMS
  • Доработка модулей и компонентов для указанных CMS, добавление нестандартного функционала
  • Разработка лендингов (landing-pages)

По все вопросам обращайтесь через форму обратной связи

Скачать

Предлагаю вашему вниманию: