Знакомая картина: скрипт вернул ID, в админке новый товар есть, а на сайте его нет. Первый импульс — «почистить кеш». Иногда это действительно помогает, но чаще кеш просто оказывается первым подозреваемым, потому что его легко назвать. Давайте сначала отделим факт записи от публичной видимости и пройдём путь теми же условиями, которыми живёт каталог.
Постановка проблемы
Админка и публичный компонент редко показывают одинаковую выборку. Админка может отобразить неактивный элемент, а каталог фильтрует по ACTIVE, датам активности, разделу, правам, цене, наличию и проектным свойствам. Поэтому вопрос «почему элемент не виден?» нельзя решать одной командой. Нужен короткий список слоёв и доказательство на каждом. Цена ошибки — повторная загрузка товара или очистка кеша вместо исправления данных.
Полезно сразу сохранить два разных наблюдения: «запись читается по ID без ограничений» и «запись попадает в публичную выборку». Между ними могут стоять несколько независимых условий. Если журнал хранит только успешный ID, а не фильтр и результат контрольного запроса, следующему разработчику останется лишь гадать, какая граница исключила товар.
Проверяем по слоям
| Слой | Что проверяем | Как получить доказательство |
|---|---|---|
| Запись | Add вернул ID, LAST_ERROR пуст | Лог результата и внешний ID операции |
| Инфоблок | ACTIVE, даты, символьный код, раздел | Контрольная выборка с теми же базовыми фильтрами |
| Свойства | Обязательная связь, SKU, картинка, проектные флаги | Чтение конкретных свойств для созданного ID |
| Каталог | Цена, остаток, доступность — если компонент их требует | Проверка конфигурации каталога и товарных параметров |
| Публичный путь | Фильтр компонента, права, кеш и индекс | Повтор сценария от имени нужного пользователя |
Контрольный запрос вместо догадки
Документация CIBlockElement::GetList описывает фильтры ACTIVE, ACTIVE_DATE и выбор нужных полей. Ниже не универсальный каталоговый запрос, а диагностическая проба. Она отвечает на первый важный вопрос: проходит ли наш элемент хотя бы базовые условия публичной выдачи. Если нет — проблему надо искать в данных, а не в шаблоне.
<?php
const PRODUCT_IBLOCK_ID = 12;
$result = CIBlockElement::GetList(
[],
[
"IBLOCK_ID" => PRODUCT_IBLOCK_ID,
"=ID" => $elementId,
"ACTIVE" => "Y",
"ACTIVE_DATE" => "Y",
],
false,
["nTopCount" => 1],
["ID", "IBLOCK_ID", "NAME", "CODE", "ACTIVE", "DATE_ACTIVE_FROM", "DATE_ACTIVE_TO"]
);
$row = $result->Fetch();
if ($row === false) {
throw new RuntimeException("Элемент не проходит базовый публичный фильтр");
}
Где здесь каталог
Элемент инфоблока и товарная часть каталога — соседние, но разные уровни. Если публичный компонент требует цену, остаток или связь торгового предложения с товаром, одного CIBlockElement::Add недостаточно. Документация каталога отдельно описывает товарные параметры; в старом коде можно встретить CCatalogProduct::Add, но текущая документация помечает его устаревшим и рекомендует модель \Bitrix\Catalog\Model\Product. Для исторического проекта это не повод переписывать всё за вечер, а повод явно зафиксировать используемую версию API и не смешивать создание элемента с догадкой о его товарном состоянии.
Мини-матрица симптомов
| Симптом | Самая частая причина | Безопасное следующее действие |
|---|---|---|
| Нет ID | Ошибка обязательного поля, свойства или прав | Вывести LAST_ERROR и входной внешний ID |
| ID есть, базовый GetList пуст | ACTIVE, дата, инфоблок или неверный ID | Сначала читать поля элемента без публичных фильтров |
| GetList есть, карточки нет | Дополнительный фильтр компонента, раздел, права, URL | Сравнить фильтр и маршрут компонента с контрольной выборкой |
| Карточка есть, нельзя купить | Не настроены параметры каталога, цена или остаток | Проверить товарный слой отдельно от инфоблока |
| После изменения появляется не сразу | Кеш или индекс | Подтвердить корректность данных и только затем адресно обновлять кеш/индекс |
Почему не стоит начинать с очистки кеша
Потому что очистка кеша скрывает различие между двумя ситуациями: данные корректны, но слой кеширования устарел; или данные с самого начала не удовлетворяют фильтру. В первом случае нужна адресная стратегия инвалидирования. Во втором — очистка не решит проблему, а только добавит шума. Хорошая диагностика оставляет после себя не только исправленный товар, но и понимание, какое условие не было выполнено.
Чек-лист перед закрытием задачи
- Зафиксировать ID созданного элемента и внешний идентификатор операции.
- Считать элемент без публичных ограничений и проверить, что ожидаемые поля и свойства сохранены.
- Повторить контрольную выборку с
ACTIVEиACTIVE_DATE. - Проверить условия конкретного компонента: раздел, права, проектные фильтры, URL.
- Если это товар — отдельно проверить цену, остаток и доступность, не смешивая этот слой с данными инфоблока.
- Только после этого проверять кеш и индекс; зафиксировать, какое именно действие обновляет их в данном проекте.
Проверяемые источники
- CIBlockElement::Add — контракт метода, обработчики до и после записи, ID и LAST_ERROR
- CIBlockElement::GetList — фильтры ACTIVE, ACTIVE_DATE и выборка полей элемента
- CCatalogProduct::Add и актуальная модель Catalog — параметры товарного элемента и версия API
Итог
Фраза «элемент есть в админке» говорит только о том, что одна запись сохранилась. Для каталога этого недостаточно. Если идти от ID к базовой выборке, от неё к товарному слою и только затем к кешу, причина обычно находится быстро. И самое приятное: на следующей похожей задаче уже не нужно вспоминать магическую кнопку очистки — есть нормальный порядок проверки.