Фильтр по множественному свойству по AND логике

  • Роман Цуканов
    Разработчик
  • Дата публикации
    21.06.2020
  • Категория
    1С-Битрикс
arrfilter AND
Задача:Нужно отфильтровать элементы по нескольким значениям множественного свойства с логикой AND.

Сложные фильтры в битриксе не так очевидны, как кажется. Логика OR прекрасно работает, а вот AND…

На сайте помимо всего прочего присутствуют два инфоблока: центры оказания услуг с координатами на карте и контактами и непосредственно инфоблок самих услуг, оказываемых данными центрами. Чтобы связать центры и услуги, у инфоблока центров есть дополнительное множественное свойство SERVICES типа «Привязка к элементам» инфоблока услуг. На странице фильтрации присутствуют чекбоксы данных услуг.

Задача заключается в том, чтобы при выборе нескольких услуг отображались только те центры, к которым привязаны именно все выбранные в фильтре услуги, а не какая-либо одна из них. Иными словами в выборке должна срабатывать логика «И», а не «ИЛИ». Нам нужно получить список ID элементов, которые мы потом скормим компоненту для корректного отображения результатов.

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

Итак, представляем Вам рабочее решение данной задачи, собранное по крупицам из разных источников.

if(!empty($_GET['services'])){
    $arrItemsIds = array();

    $arrFilter = array(
                    "IBLOCK_ID" => 33,
                    "=ACTIVE" => "Y",
                );

    foreach ($_GET['services'] as $key => $serviceId) {
        $arrFilter[] = array("ID" => CIBlockElement::SubQuery("ID", array("IBLOCK_ID" => 33, "PROPERTY_SERVICES" => $serviceId)));
    }

    $iterator = \CIBlockElement::GetList(
                                        array(),
                                        $arrFilter,
                                        false,
                                        false,
                                        array('ID')
                                    );

      while ($arItem = $iterator->Fetch()) {
          $arrItemsIds[] = $arItem['ID'];
      }

      $GLOBALS['arrFilterСto'][] = array('ID' => $arrItemsIds);
}

Что происходит выше?

Сначала проверяем на пустоту наш массив $_GET. Под ключом «services» летят выбранные в фильтре услуги. Далее, на строчках 4-7 определяем базовые настройки фильтра (нужны только активные элементы инфоблока, IBLOCK_ID которого равен 33). Бежим циклом по нашему массиву $_GET[‘services’] и динамически дособираем наш массив фильтрации  $arrFilter используя подзапросы.

Ну а дальше все просто: с помощью метода GetList вытаскиваем ID необходимых нам элементов и присваиваем их значение нашему глобальному фильтру.

2 Комментариев
  • muzanaka
    2022-12-21 08:44:03

    Спасибо за фидбек. Рады, что кому-то пригодилось.

  • Александр
    2022-12-20 12:42:58

    Спасибо тебе за код! Прям моя задача была!

Оформить заказ в Devstages