Files
progcode/editorial/agent-rewrites/360.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
14 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": 360,
"slug": "editorial-2018-01-practice-bitrix-elements",
"title": "CIBlockElement::Add: как не потерять ошибку и проверить результат",
"excerpt": "ID элемента ещё не означает готовую карточку. Разбираем контракт CIBlockElement::Add, ошибки LAST_ERROR, свойства, события и контрольную выборку, которая отделяет сохранённую запись от рабочего результата.",
"contentHtml": "<p>Симптом знакомый: импорт получил ID элемента Bitrix, но карточка не открывается, не попадает в каталог или показывает пустые свойства. В админке запись есть. В публичной выборке её нет. Цена ошибки — повторный импорт, дубли, ручное восстановление свойств и потерянное время на поиск причины в кеше.</p>\n<p><strong>Тезис:</strong> вызов <code>CIBlockElement::Add</code> завершает только операцию записи. Готовый результат требует ещё трёх проверок: ошибка не потеряна, обязательные данные сохранены, пользовательская выборка видит элемент.</p>\n<h2>Что происходит при добавлении</h2>\n<p>Метод получает массив полей: <code>IBLOCK_ID</code>, <code>NAME</code>, <code>CODE</code>, активность, раздел и, при необходимости, <code>PROPERTY_VALUES</code>. Перед записью Bitrix вызывает обработчики до добавления. Они могут изменить поля или отменить операцию. После успешной записи срабатывает событие после добавления. Поэтому вызов может иметь скрытые условия из <code>init.php</code>.</p>\n<figure><img src=\"/assets/editorial/2018/bitrix-catalog-workflow.png\" alt=\"Путь от входных данных к элементу инфоблока и контрольной проверке карточки\" /><figcaption>ID — промежуточный результат. Рабочую карточку подтверждает контрольная выборка.</figcaption></figure>\n<p>При успехе объект возвращает положительный ID. При ошибке возвращается <code>false</code>, а причина лежит в <code>LAST_ERROR</code>. Нельзя молча продолжать импорт после <code>false</code>. Сначала сохраните причину, внешний ключ и контекст вызова.</p>\n<h2>Контракт входных данных</h2>\n<p>Определите правила именно вашего инфоблока. В учебном примере обязательны название и символьный код. Число <code>12</code>, коды свойств и имена входных полей — условные. Они не описывают production-конфигурацию.</p>\n<table><caption>Контракт добавления учебного товара</caption><thead><tr><th scope=\"col\">Участок</th><th scope=\"col\">Что передаём</th><th scope=\"col\">Как проверяем</th></tr></thead><tbody><tr><td>Идентификация</td><td><code>IBLOCK_ID</code> и внешний ключ</td><td>Инфоблок известен, внешний ключ не пустой</td></tr><tr><td>Поля</td><td><code>NAME</code>, <code>CODE</code>, <code>ACTIVE</code></td><td>Название и код прошли валидацию</td></tr><tr><td>Свойства</td><td>Обязательные значения в <code>PROPERTY_VALUES</code></td><td>Коды и типы значений совпадают со схемой</td></tr><tr><td>Повтор</td><td>Правило для известного внешнего ключа</td><td>Повтор обновляет, пропускает или останавливает операцию</td></tr></tbody></table>\n<p>Внешний ключ нужен вызывающему коду. Импорт может повториться после сетевого сбоя. Если перед каждым повтором без проверки вызывать <code>Add</code>, система создаст несколько элементов с одним товаром. Идемпотентность — отдельное правило сервиса, а не свойство метода Bitrix.</p>\n<h2>Рабочий пример: создаём черновик</h2>\n<p>Черновик остаётся неактивным, пока зависимые данные не прошли проверку. Это защищает публичный каталог от полуготовой записи. В конкретном проекте вместо исключений можно использовать собственный тип результата. Учебные ID и коды свойств нужно заменить.</p>\n<pre><code>&lt;?php\n$element = new CIBlockElement();\n$id = $element-&gt;Add([\"IBLOCK_ID\" =&gt; 12, \"NAME\" =&gt; $name, \"CODE\" =&gt; $code, \"ACTIVE\" =&gt; \"N\", \"PROPERTY_VALUES\" =&gt; [\"EXTERNAL_ID\" =&gt; $externalId]]);\nif ($id === false) { throw new RuntimeException($element-&gt;LAST_ERROR ?: \"Ошибка Add\"); }\nreturn (int)$id;</code></pre>\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><code>false</code> из метода</td><td>Поле не прошло проверку или сработал обработчик</td><td>Сохранить <code>LAST_ERROR</code> и входной ключ</td><td>Исправить вход или правило; не повторять вслепую</td></tr><tr><td>ID есть, карточки нет</td><td>Элемент неактивен, не подходит фильтру или закрыт правами</td><td>Чтение по ID и повтор публичного фильтра</td><td>Разделить запись и выдачу</td></tr><tr><td>Карточка пустая</td><td>Свойство не передали или перепутали код</td><td>Прочитать поля и свойства отдельно</td><td>Сверить схему и <code>PROPERTY_VALUES</code></td></tr><tr><td>Появились дубли</td><td>Повтор не проверяет внешний ключ</td><td>Найти существующий элемент до <code>Add</code></td><td>Выбрать обновление, пропуск или остановку</td></tr><tr><td>Данные меняются после Add</td><td>Обработчик до добавления изменяет массив</td><td>Проверить зарегистрированные события</td><td>Общий инвариант оставить в обработчике</td></tr></tbody></table>\n<h2>Свойства: передать сразу или обновить отдельно</h2>\n<p>Обязательные свойства лучше передать в <code>PROPERTY_VALUES</code> во время добавления. Точечное обновление полезно позже, когда нужно изменить один статус. Оно не становится доказательством готовности. После важного изменения выполните контрольное чтение.</p>\n<pre><code>&lt;?php\nCIBlockElement::SetPropertyValuesEx($elementId, 12, [\"SYNC_STATUS\" =&gt; \"ready\"]);\n// Учебный пример: после вызова читаем свойство и публичную выборку.</code></pre>\n<p>Не передавайте неполный набор свойств, если проект трактует отсутствующее значение как очистку. Для многозначных, файловых и списочных свойств формат зависит от типа. Сначала сверяйте схему инфоблока и документацию.</p>\n<h2>Граница событий</h2>\n<p><code>OnBeforeIBlockElementAdd</code> подходит для общего инварианта. Например, конкретный инфоблок не принимает пустой <code>CODE</code> из любого источника. Обработчик не должен содержать правила одной формы, сетевые вызовы и тяжёлую бизнес-логику. Иначе консольный импорт начнёт зависеть от скрытого поведения веб-приложения.</p>\n<p>Сервис отвечает за намерение операции: подготовить поля, проверить вход, обработать повтор и перевести <code>LAST_ERROR</code> в результат. Событие страхует общий барьер. Обработчик после добавления запускает побочные действия, но не должен создавать второй элемент при ошибке уведомления или индексации.</p>\n<h2>Порядок действий</h2>\n<ol><li>Назовите инфоблок, внешний ключ и обязательные поля. Запишите, что считается готовым элементом.</li><li>Проверьте повтор по внешнему ключу до вызова <code>Add</code>.</li><li>Подготовьте массив полей с явной активностью и свойствами.</li><li>Вызовите <code>Add</code>. При <code>false</code> сохраните <code>LAST_ERROR</code> и остановите операцию.</li><li>Прочитайте элемент по ID без публичных фильтров. Проверьте поля, раздел и свойства.</li><li>Повторите выборку с фильтрами каталога: активность, даты, раздел, права, цена и остаток, если они входят в сценарий.</li><li>Только после успешной контрольной выборки включите элемент или поставьте статус готовности.</li><li>Если выборка не дала запись, не чистите кеш автоматически. Сравните фильтр с сохранёнными данными.</li></ol>\n<h2>Что не сработает</h2>\n<p>Проверка только ID не ловит пустые свойства и ограничения публичной выборки. Игнорирование <code>LAST_ERROR</code> превращает понятную ошибку в пропавший товар. Очистка всего кеша маскирует неверный фильтр. Автоматическая транслитерация без проверки уникальности создаёт конфликт кодов. Повторный <code>Add</code> после таймаута создаёт дубль, если внешний ключ не участвует в решении.</p>\n<h2>Ограничения и критерий готовности</h2>\n<p>Статья использует учебный инфоблок, условный ID и условные коды свойств. Здесь нет production-измерений и утверждений о конкретной конфигурации. Реальный проект может добавлять документооборот, поиск, цены, остатки, права, кеш и обработчики. Каждый слой требует отдельной проверки.</p>\n<p>Операция готова, когда другой инженер может повторить её на тестовом инфоблоке и получить четыре доказательства: положительный ID, сохранённые обязательные поля и свойства, отсутствие неожиданного дубля по внешнему ключу, запись в той же публичной выборке, которую использует пользовательский сценарий. При отрицательном результате готовность не объявляется.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/add.php?print=Y\" target=\"_blank\" rel=\"noopener\">CIBlockElement::Add</a> — параметры, <code>PROPERTY_VALUES</code>, события, ID и <code>LAST_ERROR</code>.</li><li><a href=\"https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/getlist.php\" target=\"_blank\" rel=\"noopener\">CIBlockElement::GetList</a> — контрольная выборка и фильтры.</li><li><a href=\"https://dev.1c-bitrix.ru/api_help/iblock/classes/ciblockelement/setpropertyvaluesex.php\" target=\"_blank\" rel=\"noopener\">CIBlockElement::SetPropertyValuesEx</a> — точечное изменение свойств.</li></ul>"
}