8 lines
14 KiB
JSON
8 lines
14 KiB
JSON
{
|
||
"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><?php\n$element = new CIBlockElement();\n$id = $element->Add([\"IBLOCK_ID\" => 12, \"NAME\" => $name, \"CODE\" => $code, \"ACTIVE\" => \"N\", \"PROPERTY_VALUES\" => [\"EXTERNAL_ID\" => $externalId]]);\nif ($id === false) { throw new RuntimeException($element->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><?php\nCIBlockElement::SetPropertyValuesEx($elementId, 12, [\"SYNC_STATUS\" => \"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>"
|
||
}
|