Скрипт после импорта вызывает CIBlockElement::GetByID(4821), GetNext() отдает NAME, а PROPERTY_ARTICLE пустой. В админке свойство заполнено, каталог на сайте элемент не показывает. Частая причина: GetByID не тянет свойства и не проверяет ACTIVE, плюс путаница IBLOCK_ID. Ниже - decision-tree: GetByID для полей, GetList для витрины, GetPropertyValuesArray для свойств, чек-лист перед Update.
CIBlockElement::GetByID($ID) в 1С-Битрикс: Управление сайтом - статический метод, возвращающий CIBlockResult с полями элемента по глобальному ID; свойства отдельно через GetList, GetProperty, GetPropertyValues или D7 ORM getByPrimary. Сегодня: подключите iblock, проверьте ID и ACTIVE через GetByID, свойства читайте GetList+GetProperties или GetPropertyValuesArray, перед Update сверьте PROPERTY_VALUES с прочитанным массивом.
Речь про 1С-Битрикс: Управление сайтом, не про Bitrix24 CRM. Элемент инфоблока - товар, новость, услуга в каталоге CMS. Создали запись через CIBlockElement::Add - следующий шаг прочитать карточку перед правкой через CIBlockElement::Update.
Разберите, когда читать элемент по ID в коде, а не в админке
На практике GetByID и связанные методы нужны, когда PHP-код должен узнать текущее состояние карточки: cron сверяет импорт, API отдает данные, скрипт перед Update читает PROPERTY_VALUES. В админке то же видно глазами, но автоматизация без read-path ломается на первом же несовпадении ID.
| Ситуация | Админка | GetByID / GetList / GetPropertyValues |
|---|---|---|
| Проверить одну карточку | Быстрее | Избыточно |
| Импорт: сравнить поля до Update | Нереально в цикле | Обязателен API |
| Витрина: только ACTIVE=Y | Фильтр в списке | GetList с ACTIVE, не GetByID |
| Нужны свойства enum и файлы | Вкладка свойств | GetProperties / GetPropertyValuesArray |
Делайте: читайте перед записью в CRUD-цепочке Add → read → Update. Не делайте: Update вслепую без текущих PROPERTY_VALUES - детали в гайде по Update.
Что такое CIBlockElement::GetByID и когда его хватает
GetByID - статический метод: по глобальному числовому ID возвращает объект CIBlockResult с полями элемента (NAME, ACTIVE, IBLOCK_ID, IBLOCK_SECTION_ID и др.). Это не массив и не D7-сущность: данные забираете через GetNext(). Метод не проверяет публикацию (ACTIVE) и не отсекает историю версий - для активных элементов на витрине в справке рекомендуют GetList.
Нужен GetByID, когда достаточно полей записи и вы сознательно читаете и неактивные элементы (staging, отладка импорта). Не нужен, если ожидаете PROPERTY_* в том же вызове - свойства GetByID не загружает.
Выполните минимальный GetByID: модуль, GetNext и проверка IBLOCK_ID
- Модуль:
Loader::includeModule('iblock'). - Вызов:
$rs = CIBlockElement::GetByID($elementId);- только ID, без IBLOCK_ID в параметрах. - Чтение:
$ar = $rs->GetNext();- false, если ID не существует. - Сверка: сравните
$ar['IBLOCK_ID']с ожидаемым инфоблоком проекта. - ACTIVE: проверьте
$ar['ACTIVE']- N объясняет пустой публичный GetList с фильтром ACTIVE=Y.
<?php
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
$elementId = 4821;
$rs = CIBlockElement::GetByID($elementId);
if ($ar = $rs->GetNext()) {
// поля есть; свойств PROPERTY_* здесь нет
$iblockId = (int)$ar['IBLOCK_ID'];
$isActive = ($ar['ACTIVE'] === 'Y');
} else {
// ID не найден в базе
}
Типичная ошибка: ID взят из внешней системы, но элемент в другом IBLOCK_ID - GetByID вернет данные, а GetList с вашим фильтром IBLOCK_ID - пусто. Второй частый кейс: элемент есть, ACTIVE=N, витрина молчит.
Делайте: логируйте IBLOCK_ID и ACTIVE сразу после GetNext. Не делайте: путать CCatalogProduct::GetByID с CIBlockElement::GetByID - каталог и инфоблок это разные API.
Прочитайте свойства: GetList, GetProperties и GetPropertyValuesArray
Свойства - отдельный слой. Три рабочих пути для одного элемента:
- GetList + GetNextElement()->GetProperties() - классика в шаблонах и скриптах.
- GetProperty($iblockId, $elementId, ['CODE' => 'ARTICLE']) - точечно 1-2 свойства.
- GetPropertyValuesArray - batch даже для одного ID, меньше N+1 в циклах.
$rs = CIBlockElement::GetList(
[],
['ID' => $elementId, 'IBLOCK_ID' => $iblockId],
false,
false,
['ID', 'NAME', 'DETAIL_PAGE_URL', 'PROPERTY_ARTICLE', 'PROPERTY_COLOR']
);
if ($ob = $rs->GetNextElement()) {
$fields = $ob->GetFields();
$props = $ob->GetProperties();
$article = $props['ARTICLE']['VALUE'];
$colorText = $props['COLOR']['VALUE_ENUM']; // список: текст, не ID
}
Для списков (select) в VALUE часто лежит ID enum - на вывод берите VALUE_ENUM или разберите ID через CIBlockPropertyEnum. Для файла: CFile::GetFileArray($props['FILE']['VALUE']) - VALUE это ID файла в b_file.
GetPropertyValuesArray удобен, когда поля уже собрали GetList, а свойства нужно догрузить одним вызовом:
$elements = [$elementId => ['ID' => $elementId]];
CIBlockElement::GetPropertyValuesArray(
$elements,
$iblockId,
['ID' => $elementId],
['CODE' => ['ARTICLE', 'COLOR', 'FILE']]
);
$props = $elements[$elementId]['PROPERTIES'];
Делайте: propertyFilter по CODE, если свойств много. Не делайте: GetByID в цикле на тысячах ID - для массива используйте batch GetList и GetPropertyValuesArray, см. GetList vs D7 ORM.
Выберите GetList для одного элемента вместо GetByID
| Критерий | CIBlockElement::GetByID | CIBlockElement::GetList (один ID) |
|---|---|---|
| Фильтр ACTIVE=Y | Нет | Да, в arFilter |
| Свойства в выборке | Нет | PROPERTY_CODE в arSelect |
| DETAIL_PAGE_URL | Не всегда удобно | Подставляется в select |
| Скорость для одного ID | Минимальный запрос полей | Чуть тяжелее, зато полный снимок |
Decision tree:
Нужны только поля и неважен ACTIVE? → GetByID → GetNext().
Витрина / только опубликованные? → GetList с ID + IBLOCK_ID + ACTIVE=Y.
Много свойств или enum/файлы? → GetNextElement + GetProperties или GetPropertyValuesArray.
Новый код на D7? → getByPrimary / wakeUp - подробнее в сравнении GetList и ORM.
Делайте: GetList, когда нужен DETAIL_PAGE_URL и PROPERTY_* в одном проходе. Не делайте: полагаться на сниппеты "GetByID возвращает все свойства" - это не так для legacy API.
Сверьте прочитанные данные перед CIBlockElement::Update
В реальном проекте workflow read → write выглядит так: прочитали PROPERTY_VALUES, сравнили с тем, что пойдет в Update, изменили только отличия. Так вы не затрете множественные свойства и не отправите в список текст вместо enum ID. Удаление карточки - отдельный путь через CIBlockElement::Delete, не путайте с "не нашли" при чтении.
Схема: GetList/GetPropertyValuesArray → массив $current → правки → Update с PROPERTY_VALUES → повторный GetList для проверки.
Нужен аудит обмена или импорта на staging - обсудите проект, примеры внедрений - портфолио.
Проверьте чек-лист на staging: активный, неактивный, пустой результат
- Активный элемент: GetList с ACTIVE=Y возвращает NAME и нужные PROPERTY_*; VALUE_ENUM читаемый.
- Неактивный (ACTIVE=N): GetByID находит, публичный GetList с ACTIVE=Y - пусто; это ожидаемо.
- Несуществующий ID: GetNext() дает false - не путать с "пустыми свойствами".
- Множественное свойство: GetProperties возвращает массив VALUE; один код - несколько строк.
- Файл: VALUE - число, путь через CFile::GetPath или GetFileArray.
Делайте: три тест-кейса в CI перед выкладкой на прод. Не делайте: отладку только на активных карточках, если импорт трогает черновики.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: CIBlockElement::GetByID, GetList, GetPropertyValuesArray, практика внедрений CMS.
Частые вопросы
Чем GetByID отличается от GetList для одного элемента?
CIBlockElement::GetByID($ID) возвращает только поля по глобальному ID и не проверяет ACTIVE. CIBlockElement::GetList с фильтром ID + IBLOCK_ID (+ ACTIVE=Y для витрины) дает те же поля плюс PROPERTY_* в arSelect и корректный DETAIL_PAGE_URL. Для свойств GetByID недостаточен - нужен GetList с GetNextElement или GetPropertyValuesArray.
Как получить все свойства элемента инфоблока?
Вызовите GetList по ID и IBLOCK_ID, затем GetNextElement()->GetProperties() - полный массив $props['CODE']['VALUE']. Альтернатива: GetPropertyValuesArray с propertyFilter по CODE. GetByID свойства не вернет.
Что возвращает GetPropertyValues для списка (select)?
В VALUE - ID enum, в VALUE_ENUM (при GetProperties или extMode) - человекочитаемый текст. Для Update передавайте ID enum, не строку "Красный". Детали типов - в гайде по CIBlockPropertyEnum.
Как прочитать файл из свойства элемента?
После GetProperties возьмите $fileId = $props['FILE']['VALUE'] - это ID в b_file. Путь: CFile::GetPath($fileId) или CFile::GetFileArray($fileId) для SRC и размеров. Не путайте с полем PREVIEW_PICTURE в GetNext() без свойств.
Как связаны GetByID и CIBlockElement::Update?
Перед Update прочитайте текущие PROPERTY_VALUES через GetList+GetProperties или GetPropertyValuesArray, сравните с новыми данными и обновите только измененные ключи. Так вы избежите затирания множественных свойств - см. гайд по Update.
Почему CIBlockElement::GetByID возвращает false?
Чаще всего ID не существует в b_iblock_element. Реже: не подключен модуль iblock, опечатка в переменной $elementId. Если GetByID находит запись, а GetList пустой - проверьте IBLOCK_ID в фильтре и ACTIVE=Y на витрине.
Есть ли D7-аналог GetByID для одного элемента?
Да: для инфоблока 2.0 - ElementXxxTable::getByPrimary($id) или Iblock::wakeUp($iblockId)->getEntityDataClass()::getByPrimary. Свойства в D7 читаются отдельно. Сравнение legacy и ORM - в статье про GetList vs D7 ORM.