Разработка фильтрации по размерам 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Разработка фильтрации по размерам 1С-Битрикс
Средняя
~1-2 недели
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1238
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    844
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    582
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    749
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    981

Разработка фильтрации по размерам 1С-Битрикс

Фильтр по размерам в каталогах одежды, обуви и мебели работает иначе, чем большинство других фильтров. Размер — как правило, свойство торгового предложения, а не родительского товара. Пользователь хочет видеть только товары, у которых его размер в наличии, — не просто товары, у которых этот размер когда-либо существовал. Разница принципиальная и требует фильтрации с проверкой остатков.

Архитектура данных для размеров

Товар (инфоблок каталога)
  └── Торговые предложения (инфоблок торговых предложений)
        ├── PROPERTY_SIZE = "S"  CATALOG_QUANTITY = 3
        ├── PROPERTY_SIZE = "M"  CATALOG_QUANTITY = 0
        └── PROPERTY_SIZE = "L"  CATALOG_QUANTITY = 7

Фильтр «размер M» при включённом «Только в наличии» не должен показывать этот товар — предложение M в наличии отсутствует.

Хранение размеров

Текстовое свойство (S, M, L, XL) — простые каталоги. XML_ID = S, VALUE = S или локализованное Маленький.

Числовое свойство (36, 37, 38... для обуви) — удобно для диапазонной фильтрации.

Сложные размеры (32/34, EU 42 / US 9) — хранятся как перечисление с кодом и несколькими отображениями.

Получение размеров с учётом остатков

function getAvailableSizes(int $offersIblockId): array
{
    $sizes = [];

    // Получаем только предложения с ненулевым остатком
    $res = CIBlockElement::GetList(
        [],
        [
            'IBLOCK_ID'         => $offersIblockId,
            'ACTIVE'            => 'Y',
            '>CATALOG_QUANTITY' => 0,
        ],
        ['PROPERTY_SIZE'],
        false,
        ['PROPERTY_SIZE']
    );

    while ($item = $res->Fetch()) {
        $sizeId = $item['PROPERTY_SIZE_ENUM_ID'];
        $sizeValue = $item['PROPERTY_SIZE_VALUE'];

        if ($sizeId && !isset($sizes[$sizeId])) {
            $sizes[$sizeId] = [
                'id'    => $sizeId,
                'xmlId' => $item['PROPERTY_SIZE_ENUM_XML_ID'],
                'value' => $sizeValue,
                'sort'  => 0, // заполним ниже
            ];
        }
    }

    // Сортировка из настроек свойства
    if (!empty($sizes)) {
        $enumRes = CIBlockPropertyEnum::GetList(
            ['SORT' => 'ASC'],
            ['IBLOCK_ID' => $offersIblockId, 'CODE' => 'SIZE']
        );
        $sortMap = [];
        while ($enum = $enumRes->Fetch()) {
            $sortMap[$enum['ID']] = intval($enum['SORT']);
        }
        foreach ($sizes as &$size) {
            $size['sort'] = $sortMap[$size['id']] ?? 999;
        }
        usort($sizes, fn($a, $b) => $a['sort'] <=> $b['sort']);
    }

    return array_values($sizes);
}

Фильтрация каталога по размеру с остатком

function getProductIdsBySize(
    int $catalogIblockId,
    int $offersIblockId,
    array $sizeXmlIds,
    bool $onlyInStock = true
): array {
    if (empty($sizeXmlIds)) return [];

    $offerFilter = [
        'IBLOCK_ID'   => $offersIblockId,
        'ACTIVE'      => 'Y',
        'PROPERTY_SIZE' => $sizeXmlIds,
    ];

    if ($onlyInStock) {
        $offerFilter['>CATALOG_QUANTITY'] = 0;
    }

    $productIds = [];
    $res = CIBlockElement::GetList(
        [],
        $offerFilter,
        false,
        false,
        ['PROPERTY_CML2_LINK']
    );

    while ($row = $res->GetNext()) {
        if ($pid = intval($row['PROPERTY_CML2_LINK_VALUE'])) {
            $productIds[$pid] = true;
        }
    }

    return array_keys($productIds);
}

UI: сетка размеров

$availableSizes = getAvailableSizes(OFFERS_IBLOCK_ID);
$selectedSizes = array_map('htmlspecialchars', (array)($_GET['SIZE'] ?? []));
?>
<div class="filter-block filter-block--sizes">
    <h3 class="filter-block__title">Размер</h3>
    <div class="size-grid">
        <?php foreach ($availableSizes as $size): ?>
        <?php $isSelected = in_array($size['xmlId'], $selectedSizes); ?>
        <label class="size-option <?= $isSelected ? 'is-selected' : '' ?>">
            <input type="checkbox"
                   name="SIZE[]"
                   value="<?= htmlspecialchars($size['xmlId']) ?>"
                   <?= $isSelected ? 'checked' : '' ?>>
            <span class="size-label"><?= htmlspecialchars($size['value']) ?></span>
        </label>
        <?php endforeach; ?>
    </div>
</div>

CSS сетки размеров

.size-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.size-option input[type="checkbox"] {
  display: none;
}

.size-label {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  height: 36px;
  padding: 0 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  user-select: none;
}

.size-option.is-selected .size-label {
  background: #1a1a1a;
  border-color: #1a1a1a;
  color: #fff;
}

.size-option:hover:not(.is-selected) .size-label {
  border-color: #999;
}

Кеширование доступных размеров

$cacheId = 'available_sizes_' . OFFERS_IBLOCK_ID;
$cache = \Bitrix\Main\Data\Cache::createInstance();

if ($cache->initCache(600, $cacheId, '/catalog/filter/')) {
    $availableSizes = $cache->getVars();
} else {
    $availableSizes = getAvailableSizes(OFFERS_IBLOCK_ID);
    $cache->startDataCache();
    $cache->endDataCache($availableSizes);
}

Инвалидация при изменении остатков через тег кеша или агент каждые 10 минут.

Сроки выполнения

Фильтр по размерам через свойство перечисления без проверки остатков — 4–8 часов. Полная реализация с проверкой наличия по SKU, кешированием, кастомным UI и сортировкой размеров — 2–3 рабочих дня.