Yandex Metrika
sanches.free 1 просмотр

Настройки показа свойств инфоблока в списке и на детальной: PropertyFeature и перенос

Зачем PropertyFeature

В админке у свойств инфоблока давно есть две галочки: показывать в списке элементов и на детальной карточке. Они нужны типовым компонентам каталога и новостям, когда поля не перечисляют явно по коду — ядро смотрит на признаки feature. На практике те же режимы удобно перенести между площадками вместе с самим описанием свойств: без этого второй сайт может внезапно «потерять» столбцы в умной выдаче или SEO-блок даже при совпадающих XML.

Читать и писать набор включают методы класса \Bitrix\Iblock\Model\PropertyFeature; идентификаторы «каких свойств активны какие режимы» отдаются отдельно для списка и карточки, а сохранять удобнее через символьные коды — они человекочитаемы при сравнении двух дампов.

Выгрузка активных свойств одного инфоблока

Подключение модуля и числовой ключ инфоблока здесь условный: подставьте свой $iblockExportId. Методы getListPageShowPropertyCodes и getDetailPageShowPropertyCodes возвращают массивы идентификаторов полей свойств; по ним один раз дергается PropertyTable, чтобы собрать пары код ↔ участие в списке и на карточке.

use Bitrix\Main\Loader;
use Bitrix\Iblock\PropertyTable;
use Bitrix\Iblock\Model\PropertyFeature;

if (!Loader::includeModule('iblock')) {
    return;
}

$iblockExportId = 16;

$listPropertyIds = PropertyFeature::getListPageShowPropertyCodes($iblockExportId);
$detailPropertyIds = PropertyFeature::getDetailPageShowPropertyCodes($iblockExportId);

$listIdIndex = array_flip(array_map('intval', $listPropertyIds));
$detailIdIndex = array_flip(array_map('intval', $detailPropertyIds));

$unionIds = array_values(array_unique(array_merge(
    array_keys($listIdIndex),
    array_keys($detailIdIndex)
)));

$codesForList = [];
$codesForDetail = [];

if ($unionIds) {
    $walker = PropertyTable::getList([
        'filter' => [
            '=IBLOCK_ID' => $iblockExportId,
            '@ID' => $unionIds,
        ],
        'select' => ['ID', 'CODE'],
    ]);

    while ($row = $walker->fetch()) {
        $propertyPk = (int)$row['ID'];
        $symbolicCode = trim((string)$row['CODE']);

        if ($symbolicCode === '') {
            continue;
        }

        if (isset($listIdIndex[$propertyPk])) {
            $codesForList[] = $symbolicCode;
        }
        if (isset($detailIdIndex[$propertyPk])) {
            $codesForDetail[] = $symbolicCode;
        }
    }
}

Сохраните $codesForList и $codesForDetail как JSON или вставьте литералы в следующий скрипт на целевой площадке. Свойства без символьного кода фильтром выше отброшены: для миграции обычно проще временно завести короткий код там, где администраторы полагались только на человекочитаемое название.

Применение на другом инфоблоке

Следующий фрагмент предполагает, что нужные коды уже лежат в массивах $codesForList и $codesForDetail (подтяни́те их из сохранённого дампа первого шага). Для каждого свойства целевого инфоблока формируем явную связку режим ↔ флаг так, чтобы несуществующее в дампе поле действительно сняло галочку, а не сохранило старый режим случайным наследием.

use Bitrix\Main\Loader;
use Bitrix\Iblock\PropertyTable;
use Bitrix\Iblock\Model\PropertyFeature;

if (!Loader::includeModule('iblock')) {
    return;
}

$iblockImportId = 10;

// Подставьте значения, полученные на этапе выгрузки.
$codesForList = ['COLOR', 'WEIGHT'];
$codesForDetail = ['COLOR', 'ARTNUMBER'];

$walker = PropertyTable::getList([
    'filter' => ['=IBLOCK_ID' => $iblockImportId],
    'select' => ['ID', 'CODE', 'NAME'],
]);

$appliedListHits = 0;
$appliedDetailHits = 0;

while ($property = $walker->fetch()) {
    $symbolicCode = trim((string)$property['CODE']);

    $bundle = [
        [
            'MODULE_ID' => 'iblock',
            'IS_ENABLED' => $symbolicCode !== '' && in_array($symbolicCode, $codesForList, true)
                ? 'Y'
                : 'N',
            'FEATURE_ID' => 'LIST_PAGE_SHOW',
        ],
        [
            'MODULE_ID' => 'iblock',
            'IS_ENABLED' => $symbolicCode !== '' && in_array($symbolicCode, $codesForDetail, true)
                ? 'Y'
                : 'N',
            'FEATURE_ID' => 'DETAIL_PAGE_SHOW',
        ],
    ];

    PropertyFeature::setFeatures((int)$property['ID'], $bundle);

    if ($bundle[0]['IS_ENABLED'] === 'Y') {
        $appliedListHits++;
    }
    if ($bundle[1]['IS_ENABLED'] === 'Y') {
        $appliedDetailHits++;
    }
}

Если хотите воспроизвести конфигурацию компонента вместо жёсткой выгрузки, используйте те же массивы кодов из параметров bitrix:catalog.element или bitrix:news; механизм в базе данных остаётся тем же самым классом PropertyFeature, так что смешение «ручного» дампа и настроек шаблонов просто упрощает сверку ожиданий.

На что обратить внимание при переносе

  • Несовпадение состава свойств между инфоблоками означает, что коды без пары просто игнорируются — добавьте отчёт о «осиротевших» литералов перед финальным деплоем.
  • Выполнение только на тестовом контуре перед прогревом кешей каталога снижает риск временно «сломать» чужие шаблоны, где отбор полей смешивает галочку и своё исключение через PROPERTY_CODE.
  • Доработку стоит класть в одноразовый миграционный файл или очередь, а не в вечный bootstrap: свойства добавляются редко, а обход каждого поля дороже простого включения нужного свойства один раз после импорта.

Итог

PropertyFeature сводит галочки «список / деталь» к данным таблицы, которые можно воспроизвести между разными инфоблоками и установками. Два маленьких скрипта — выгрузка кодов по ID и восстановление с явным включением и отключением — закрывают типовой кейс синхронизации админских настроек без ручной расстановки сотни чекбоксов.

См. также: настройки свойств элементов для разделов на estrin.pw — комплементарная тема, если нужно синхронизировать привязки на уровне разделов, а не глобальные свойства элементов.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии