8 lines
20 KiB
JSON
8 lines
20 KiB
JSON
{
|
||
"index": 358,
|
||
"slug": "editorial-2018-01-field-bitrix-elements",
|
||
"title": "Почему элемент Bitrix есть в админке, но пропадает из каталога",
|
||
"excerpt": "ID после CIBlockElement::Add подтверждает запись, но не публичную видимость. Разбираем фильтры инфоблока, товарный слой, права и кеш по проверяемой цепочке.",
|
||
"contentHtml": "<p>Скрипт импорта сообщает об успехе: <code>CIBlockElement::Add</code> вернул ID. В админке элемент открывается. В каталоге его нет. Пользователь получает пустой список или старую карточку, а команда начинает очищать весь кеш. Цена ошибки — повторная загрузка того же товара, дубли, потерянное время и отсутствие доказательства, на каком условии запись исчезла.</p>\n<p><strong>Тезис:</strong> успешная запись и публичная видимость — разные факты. Сначала подтвердите, что Bitrix сохранил элемент. Затем повторите условия публичной выборки. После этого проверьте товарный слой, права, маршрут и кеш. Если запись не проходит более ранний фильтр, поздние проверки не объяснят симптом.</p>\n<h2>Поворот в расследовании: что показывает админка</h2>\n<p>На учебной копии каталога разработчик повторяет импорт и видит тот же симптом: после вызова <code>Add</code> в журнале есть ID, но гостевой список пуст. Сначала он открывает запись в админке, затем сверяет поля по ID и только после этого сравнивает публичный фильтр. Такой порядок отделяет сохранённый элемент от результата страницы.</p>\n<p>Админский список может показать неактивный элемент, запись с прошедшей датой публикации или элемент из другого раздела. Публичный компонент обычно добавляет <code>ACTIVE</code>, <code>ACTIVE_DATE</code>, раздел, свойства, доступность и собственные проектные условия. Поэтому фраза «элемент есть в админке» означает только, что одна административная выборка его нашла.</p>\n<p>У записи есть несколько границ. <code>CIBlockElement::Add</code> создаёт элемент инфоблока. Свойства сохраняются рядом с ним, но их наличие не означает, что товар готов к покупке. Цена, остаток, тип товара и торговые предложения относятся к каталожному слою. Компонент каталога может затем отфильтровать результат ещё раз. Кеш влияет только после того, как данные уже проходят действующие условия.</p>\n<figure><img src=\"/assets/editorial/2018/bitrix-visibility-diagnostic.svg\" alt=\"Цепочка диагностики Bitrix: Add, контрольная выборка, товарный слой, публичный компонент и кеш\" loading=\"lazy\" /><figcaption>Проверяйте границы слева направо. Каждая следующая проверка имеет смысл только после подтверждения предыдущей.</figcaption></figure>\n<h2>Сначала зафиксируйте результат Add</h2>\n<p>Не ограничивайтесь ID. При ошибке <code>Add</code> возвращает ложное значение, а причина доступна через <code>LAST_ERROR</code>. Сохраните внешний идентификатор импорта, ID инфоблока, название операции и результат. Если код продолжает выполнение после неуспешной записи, последующий запрос может проверять старый или пустой ID и увести расследование в сторону.</p>\n<p>Учебный фрагмент ниже показывает только форму проверки. Число инфоблока и идентификатор элемента условны. Код не доказывает, что конкретный проект использует именно такую схему импорта.</p>\n<pre><code><?php\n\nconst PRODUCT_IBLOCK_ID = 12;\n\n$fields = [\n 'IBLOCK_ID' => PRODUCT_IBLOCK_ID,\n 'NAME' => 'Учебный элемент',\n 'ACTIVE' => 'Y',\n];\n\n$element = new CIBlockElement;\n$elementId = $element->Add($fields);\n\nif (!$elementId) {\n throw new RuntimeException(\n 'Элемент не создан: ' . $element->LAST_ERROR\n );\n}\n\n$select = ['ID', 'IBLOCK_ID', 'NAME', 'CODE', 'ACTIVE',\n 'DATE_ACTIVE_FROM', 'DATE_ACTIVE_TO'];\n$stored = CIBlockElement::GetList(\n [],\n [\n 'IBLOCK_ID' => PRODUCT_IBLOCK_ID,\n '=ID' => (int) $elementId,\n ],\n false,\n ['nTopCount' => 1],\n $select\n)->Fetch();\n\nif ($stored === false) {\n throw new RuntimeException('Сохранённый элемент не читается');\n}\n\n$public = CIBlockElement::GetList(\n [],\n [\n 'IBLOCK_ID' => PRODUCT_IBLOCK_ID,\n '=ID' => (int) $elementId,\n 'ACTIVE' => 'Y',\n 'ACTIVE_DATE' => 'Y',\n ],\n false,\n ['nTopCount' => 1],\n $select\n)->Fetch();\n\nif ($public === false) {\n echo 'Элемент сохранён, но не проходит базовый публичный фильтр';\n}</code></pre>\n<p>В реальном вызове в первый аргумент <code>Add</code> передают массив полей и, при необходимости, свойств. В этом учебном примере указаны минимальные поля, а свойства проекта и товарные параметры намеренно не добавлены. Так видна граница между результатом записи и контрольным чтением: сохранённый ID ещё не отвечает на вопрос, попадёт ли элемент в каталог.</p>\n<h2>Повторите базовый публичный фильтр</h2>\n<p><code>CIBlockElement::GetList</code> возвращает элементы по переданному фильтру. Для минимальной пробы используйте тот же инфоблок, ID, <code>ACTIVE => Y</code> и <code>ACTIVE_DATE => Y</code>, которые применяет публичная выдача. Выбирайте только нужные поля. Если контрольный запрос с этими условиями пуст, ищите проблему в полях элемента, датах, инфоблоке или разделах, а не в шаблоне.</p>\n<p>Если базовая выборка возвращает строку, это ещё не доказательство видимости карточки. Компонент может требовать конкретное свойство, принадлежность к разделу, заполненный символьный код, разрешение пользователя или собственный флаг публикации. Скопируйте фильтр компонента в диагностический запрос по частям. Не заменяйте его догадкой «наверняка нужен кеш».</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<div class=\"table-scroll\"><table><caption>Матрица диагностики элемента и каталога</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Причина</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>ID не получен</td><td>Ошибка обязательного поля, свойства или прав</td><td>Проверить результат <code>Add</code> и <code>LAST_ERROR</code></td><td>Исправить входные данные; не проверять пустой ID в каталоге</td></tr><tr><td>ID есть, базовый <code>GetList</code> пуст</td><td><code>ACTIVE</code>, даты, инфоблок или ID не совпадают</td><td>Считать элемент без публичных условий и сравнить поля</td><td>Исправить запись или фильтр импорта</td></tr><tr><td>Базовый запрос есть, карточки нет</td><td>Раздел, свойство, права или фильтр компонента</td><td>Сравнить реальный фильтр компонента с контрольным</td><td>Устранить первое несовпадающее условие</td></tr><tr><td>Карточка есть, купить нельзя</td><td>Нет цены, остатка, связи SKU или доступности</td><td>Проверить товарную модель и параметры каталога отдельно</td><td>Заполнить товарный слой или изменить требование компонента</td></tr><tr><td>После исправления видна старая версия</td><td>Кеш, индекс или другой источник данных</td><td>Сначала повторить чтение в обход кеша и сравнить ключ</td><td>Точечно обновить нужный слой после подтверждения данных</td></tr><tr><td>В админке виден, у гостя нет</td><td>Права или условие показа для текущего пользователя</td><td>Повторить запрос с теми же правами, что у посетителя</td><td>Исправить доступ или явно принять ограниченную видимость</td></tr></tbody></table></div>\n<h2>Инфоблок не равен товару</h2>\n<p>В Bitrix элемент инфоблока хранит общие данные: имя, код, активность, раздел и свойства. Для каталога этого может быть мало. Простой товар, товар с торговыми предложениями и другие типы используют разные связи и состояния. Публичный код может отбрасывать элемент без корректной цены, доступного предложения или нужного остатка.</p>\n<p>Проверяйте товарный слой отдельным запросом и в терминах версии проекта. Старый код может использовать <code>CCatalogProduct</code>, а новый — классы пространства <code>\\Bitrix\\Catalog\\Product</code>. Нельзя смешивать исправление видимости инфоблока с миграцией API: сначала установите, какой слой не проходит условие, затем выбирайте совместимый способ изменения.</p>\n<p>Отрицательный путь важен. Если элемент не должен продаваться, не добавляйте цену и остаток только ради того, чтобы карточка появилась. В таком случае видимость и доступность — разные требования. Изменение товарных параметров может открыть покупку, скидки или уведомления, хотя исходная задача касалась только списка.</p>\n<h2>Почему очистка кеша редко бывает первым действием</h2>\n<p>Кеш может вернуть старую выборку, но он не исправит неактивный элемент, неверную дату или отсутствующую цену. Полная очистка также меняет поведение других страниц и создаёт лишнюю нагрузку. Если данные не проходят фильтр, после очистки результат останется пустым. Если данные корректны, нужен адресный способ инвалидирования с понятным ключом.</p>\n<p>Для проверки разделите два чтения: контрольное чтение из источника и чтение через публичный путь. Если источник уже не проходит фильтр, остановитесь на данных. Если источник проходит, а публичный ответ старый, зафиксируйте ключ кеша, время формирования и слой, который его обслуживает. Не делайте вывод по одному обновлению браузера.</p>\n<h2>Порядок действий</h2>\n<ol><li>Запишите внешний ID операции, ID инфоблока и входные данные, которые безопасно хранить в журнале.</li><li>Проверьте результат <code>CIBlockElement::Add</code>; при ошибке остановитесь и выведите <code>LAST_ERROR</code>.</li><li>Считайте элемент по ID без ограничений и подтвердите инфоблок, активность, даты, код, раздел и обязательные свойства.</li><li>Повторите базовый публичный фильтр с <code>ACTIVE</code> и <code>ACTIVE_DATE</code>; запишите, на каком условии строка исчезает.</li><li>Сравните фильтр конкретного компонента, права посетителя, раздел и проектные флаги.</li><li>Если это товар, отдельно проверьте тип товара, цену, остаток, доступность и связь торговых предложений.</li><li>Только после проверки источника сравните публичный ответ, кеш-ключ и индекс; обновляйте адресно.</li><li>Повторите чтение тем же пользователем и по тому же маршруту, где наблюдался исходный симптом.</li><li>Зафиксируйте либо исправленное условие, либо точную причину остановки. Не называйте задачу решённой по одному успешному ID.</li></ol>\n<h2>Ограничения</h2>\n<p>Эта схема не заменяет знание конфигурации конкретного инфоблока и компонента. У проекта могут быть дополнительные фильтры, торговые предложения, складские остатки, права, поиск или внешний индекс. Один <code>GetList</code> не воспроизводит автоматически весь путь страницы.</p>\n<p>Учебный код использует условный ID <code>12</code> и не выполняет реальную запись. Не запускайте его в production без заполненных полей, проверки прав и понимания побочных эффектов. Не очищайте общий кеш и не повторяйте импорт, пока не установили идемпотентность операции. В журнале не сохраняйте токены и персональные данные.</p>\n<p>Если нет доступа к фильтру компонента, правам пользователя или товарному слою, вывод должен быть ограниченным: «элемент читается по ID, но публичная причина не установлена». Это полезнее, чем неподтверждённое обвинение кеша.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Диагностика готова, когда другой инженер может пройти путь от внешнего ID до публичного запроса и увидеть результат каждой границы: запись создана, поля сохранены, базовый фильтр пройден, товарный слой соответствует типу, права совпадают, а кеш или индекс проверены последними. Для отрицательного сценария указано условие остановки и действие, которое не следует выполнять.</p>\n<p>Исправление можно считать подтверждённым только после повторного запроса по исходному публичному маршруту и с исходными правами. Он должен вернуть ожидаемый элемент, а журнал должен объяснять, какое условие изменилось. Если видимость подтверждена только в админке, задача ещё не закрыта.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php\" target=\"_blank\" rel=\"noopener noreferrer\">1С-Битрикс: CIBlockElement::GetList</a> — официальное описание фильтров, включая <code>ACTIVE</code>, даты активности и выборку полей.</li><li><a href=\"https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/add.php\" target=\"_blank\" rel=\"noopener noreferrer\">1С-Битрикс: CIBlockElement::Add</a> — официальный контракт добавления элемента и обработки результата записи.</li><li><a href=\"https://dev.1c-bitrix.ru/api_help/catalog/classes/ccatalogproduct/add.php\" target=\"_blank\" rel=\"noopener noreferrer\">1С-Битрикс: CCatalogProduct::Add</a> — официальная историческая страница метода; документация помечает его устаревшим с версии 17.6.0 и указывает замену.</li><li><a href=\"https://dev.1c-bitrix.ru/api_d7/bitrix/catalog/product/index.php\" target=\"_blank\" rel=\"noopener noreferrer\">1С-Битрикс: торговый каталог Product</a> — актуальное описание пространства имён для товаров и торговых предложений.</li></ul>"
|
||
}
|