Блог разработчика 1С-Битрикс

Как вывести одновременно активные и неактивные товары в bitrix:catalog.section

Стандартный компонент bitrix:catalog.section из коробки показывает только элементы с ACTIVE = 'Y'. Нужно, чтобы в публичном каталоге (или в админ-витрине) были видны и отключённые товары, например для страницы «Скоро в продаже» либо для внутренних проверок склада.

Активные и неактивные элементы в bitrix:catalog.section

Почему товары с ACTIVE = 'N' не попадают в выборку

В иерархии D7-компонентов фильтр собирается в методе

protected function getFilter()

у базового класса \Bitrix\Iblock\Component\ElementList, от которого наследуется CatalogSectionComponent. Там жёстко добавляется пара условий:

'ACTIVE' => 'Y',
'ACTIVE_DATE' => 'Y',

Поэтому все деактивированные элементы отсеиваются на уровне SQL и до шаблона не доходят.

Решение за один шаг: переопределяем только getFilter()

Раз компонент полностью классовый, нам не нужен component.php. Достаточно создать собственный компонент-обёртку в /local/components и подменить один-единственный метод.

/local/components/my_company/catalog.section.inactive/
    └── class.php

Шаг 1. Копируем базовый класс

Скопируйте содержимое ядрового \bitrix\components\bitrix\catalog.section\class.php целиком в class.php новой папки — это гарантирует 100 % совместимость со всеми обновлениями тайп-хинтов и приватных свойств.

Если хотите минимализм, можно унаследоваться от ядрового класса и держать в файле только переопределённые методы. Ниже показана именно «короткая» версия.

<?php
use Bitrix\Main\Loader;

/**
 * Расширенный catalog.section.
 * Показывает активные и неактивные элементы.
 */
class CatalogSectionInactiveComponent extends CatalogSectionComponent
{
    /**
     * Снимаем ограничение ACTIVE='Y'
     * и сохраняем остальную бизнес-логику фильтра.
     */
    protected function getFilter()
    {
        // 1. Базовый набор условий
        $filterFields = parent::getFilter();

        // 2. Не трогаем Big Data lazy-load
        if ($this->getAction() === 'bigDataLoad')
        {
            return $filterFields;
        }

        // 3. Убираем «лишнее» ограничение
        unset($filterFields['ACTIVE']);

        /* 4. Оставляем служебные условия родителя
              (INCLUDE_SUBSECTIONS, SECTION_ID и т.п.) */
        $filterFields['INCLUDE_SUBSECTIONS'] =
            $this->arParams['INCLUDE_SUBSECTIONS'] === 'N' ? 'N' : 'Y';

        if ($this->arParams['INCLUDE_SUBSECTIONS'] === 'A')
        {
            $filterFields['SECTION_GLOBAL_ACTIVE'] = 'Y';
        }

        if (!isset($this->arParams['BY_LINK']) || $this->arParams['BY_LINK'] !== 'Y')
        {
            if ($this->arResult['ID'])
            {
                $filterFields['SECTION_ID'] = $this->arResult['ID'];
            }
            elseif (!$this->arParams['SHOW_ALL_WO_SECTION'])
            {
                $filterFields['SECTION_ID'] = 0;
            }
            else
            {
                unset(
                    $filterFields['INCLUDE_SUBSECTIONS'],
                    $filterFields['SECTION_GLOBAL_ACTIVE']
                );
            }
        }

        return $filterFields; // и получаем товары с Y *и* N
    }
}

Копипаст или наследование?
* Наследование (пример выше) короче и чище, но при «ломающих» изменениях ядра может понадобиться доработка.
* Полная копия гарантирует стабильность независимо от версии, но требует следить за апдейтами и объёмнее в поддержке.

Шаг 2. Шаблон компонента (опционально)

Обычный шаблон catalog.section уже готов; добавим лишь визуальную отметку для неактивных:

<?php foreach ($arResult['ITEMS'] as $item):
    $inactive = $item['ACTIVE'] === 'N'; ?>
    <div class="product<?=$inactive ? ' product--inactive' : ''?>">
        <a href="<?=$item['DETAIL_PAGE_URL']?>"><?=$item['NAME']?></a>
        <?php if ($inactive): ?>
            <span class="badge badge-secondary">Скоро в наличии</span>
        <?php endif; ?>
    </div>
<?php endforeach; ?>
.product--inactive {opacity:.55;position:relative}
.product--inactive .badge {position:absolute;top:.5rem;left:.5rem}

Шаг 3. Подключение на странице

<?php
$APPLICATION->IncludeComponent(
    'my_company:catalog.section.inactive',
    '.default',
    [
        'IBLOCK_TYPE' => 'catalog',
        'IBLOCK_ID' => 12,
        'SECTION_ID' => 23,
        'PAGE_ELEMENT_COUNT' => 30,
        'PRICE_CODE' => ['BASE'],
        'CACHE_TYPE' => 'A',
        'CACHE_TIME' => 3600000,
        // остальные параметры родительского catalog.section
    ]
);

Компонент выводит все элементы (Y + N) без дополнительных флагов. Хотите оставить стандартную логику — подключайте «родной» ядровый компонент.

Важные нюансы продакшена

Тема Что учесть
Права доступа Неактивные товары могут быть скрыты сознательно. Защитите вывод if ($USER->IsAdmin()) … либо публикуйте отдельную страницу.
SEO Роботы увидят отключённые карточки. Добавьте noindex или перенаправление 302, если они не должны индексироваться.
Кеширование Чистка кеша при смене активности остаётся на Bitrix, поэтому дополнительные действия не нужны.
Производительность Отсутствие фильтра ACTIVE увеличит выборку. Используйте постраничку и выводите только нужные поля (SELECT).

Итог

  • Минимальное вмешательство — изменён один метод в наследнике.
  • Совместимость со всеми фишками catalog.section: пейджинг, Smart Filter, SKU-выборки, lazy-load.
  • Гибкость — в нужных точках можно легко вернуть стандартное поведение, подключив ядровый компонент.

Таким образом, за несколько строк кода мы получаем полноценный каталог, где менеджер видит всё, а клиент — только то, что действительно доступно к покупке.

Теги: catalog.section, активные товары, неактивные товары, вывод товаров, фильтр товаров


Валерий Макеев
11.09.2025 14:10
Сделаем вывод в браузере список всех товаров (включая неактивные) из указанного инфоблока, используя прямой вызов CIBlockElement::GetList() без фильтрации по ACTIVE, что позволит быстро проверить наличие скрытых элементов.
Код
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php';

CModule::IncludeModule("iblock");

// ID инфоблока с товарами (замените на свой)
$iblockId = 2;

// Получаем все элементы — и активные, и неактивные
$rsElements = CIBlockElement::GetList(
    ['SORT' => 'ASC'],
    [
        'IBLOCK_ID' => $iblockId,
        // НЕ указываем 'ACTIVE' => 'Y' — значит, получим и 'N' тоже
    ],
    false,
    ['nPageSize' => 20],
    ['ID', 'NAME', 'ACTIVE', 'DATE_ACTIVE_FROM', 'DETAIL_PAGE_URL']
);

echo "<h3>Товары (активные и неактивные):</h3><ul>";

while ($arElement = $rsElements->GetNext()) {
    $status = $arElement['ACTIVE'] === 'Y' ? '✅ Активен' : '⛔ Неактивен';
    echo "<li><a href='{$arElement['DETAIL_PAGE_URL']}'>{$arElement['NAME']}</a> — <strong>{$status}</strong></li>";
}

echo "</ul>";


Пример вывода

[FILE ID=554]

Стоимость услуг по разработке и сопровождению сайтов на 1C-Битрикс

Разработка корпоративного сайта

от 7 дней

от 40 000 рублей

Разработка сайта без системы оплаты заказов через корзину

* стоимость зависит от наличия верстки, использования готового решения и т.д.

Аутсорсинг

готов помочь, если нет времени

договорная

Могу взять на себя работы по full-stack

* на основе готовой верстки

Интернет-магазин на готовом решении

от 7 дней

от 40 000 рублей
запуск сайта в максимально короткие сроки

* указана минимальная стоимость. Стоимость выбранной лицензии «1С-Битрикс» оплачивается отдельно.