Files
progcode/editorial/agent-rewrites/358.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
18 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"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>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>&lt;?php\n\n$element = new CIBlockElement;\n$elementId = $element->Add($fields);\n\n\nif (!$elementId) {\n throw new RuntimeException(\n 'Element was not created: ' . $element->LAST_ERROR\n );\n}\n\n$check = CIBlockElement::GetList(\n [],\n [\n 'IBLOCK_ID' =&gt; 12,\n '=ID' =&gt; (int) $elementId,\n ],\n false,\n ['nTopCount' =&gt; 1],\n ['ID', 'IBLOCK_ID', 'NAME', 'CODE', 'ACTIVE',\n 'DATE_ACTIVE_FROM', 'DATE_ACTIVE_TO']\n);\n\n$row = $check-&gt;Fetch();\nif ($row === false) {\n throw new RuntimeException('Saved element cannot be read');\n}</code></pre>\n<p>В реальном вызове в первый аргумент <code>Add</code> передают заполненный массив полей и свойств. В примере он пуст намеренно: важна граница между результатом записи и контрольным чтением. Сохранённый ID ещё не отвечает на вопрос, попадёт ли элемент в каталог.</p>\n<h2>Повторите базовый публичный фильтр</h2>\n<p><code>CIBlockElement::GetList</code> возвращает элементы по переданному фильтру. Для минимальной пробы используйте тот же инфоблок, ID, <code>ACTIVE =&gt; Y</code> и <code>ACTIVE_DATE =&gt; Y</code>, которые применяет публичная выдача. Выбирайте только нужные поля. Если контрольный запрос с этими условиями пуст, ищите проблему в полях элемента, датах, инфоблоке или разделах, а не в шаблоне.</p>\n<p>Если базовая выборка возвращает строку, это ещё не доказательство видимости карточки. Компонент может требовать конкретное свойство, принадлежность к разделу, заполненный символьный код, разрешение пользователя или собственный флаг публикации. Скопируйте фильтр компонента в диагностический запрос по частям. Не заменяйте его догадкой «наверняка нужен кеш».</p>\n<h2>Симптом → причина → проверка → действие</h2>\n<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>\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_d7/bitrix/catalog/product/index.php\" target=\"_blank\" rel=\"noopener noreferrer\">1С-Битрикс: торговый каталог Product</a> — официальное описание классов товарного слоя и торговых предложений.</li></ul>"
}