PropertyFeature вместо ручного списка свойств каталога
Проблема/контекст
Контент-менеджер отмечает в карточке свойства галки «Показывать в списке» и «Показывать на детальной», а разработчик в своём компоненте дублирует те же коды в параметре PROPERTY_CODE. Списки расходятся при первом же изменении настроек. Эти галки хранятся не в свойстве, а в отдельной таблице b_iblock_property_feature, и у неё есть публичное API — Bitrix\Iblock\Model\PropertyFeature.
Решение с кодом
Движок фич включается опцией «Использовать параметры свойств в компонентах и формах» property_features_enabled модуля iblock (значение по умолчанию — Y). Проверка — PropertyFeature::isEnabledFeatures(): bool.
<?php
declare(strict_types=1);
use Bitrix\Iblock\Model\PropertyFeature;
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
if (PropertyFeature::isEnabledFeatures())
{
// ['COLOR', 'MATERIAL'] или null
$listCodes = PropertyFeature::getListPageShowPropertyCodes($iblockId, ['CODE' => 'Y']);
$detailCodes = PropertyFeature::getDetailPageShowPropertyCodes($iblockId, ['CODE' => 'Y']);
}
Детали, которые важны на практике:
- сигнатура —
getListPageShowPropertyCodes($iblockId, array $parameters = []): ?array; второй аргумент понимает единственный ключCODEв верхнем регистре; - без
['CODE' => 'Y']возвращаются ID свойств (строками), а не символьные коды. СCODE => 'Y'вернётсяCODE, а при пустомCODE— ID; - возвращается
null, если движок выключен,$iblockId <= 0или подходящих свойств нет. Пустого массива не будет — обрабатывайтеnullявно; - выборка фильтрует
PROPERTY.ACTIVE = 'Y'иIS_ENABLED = 'Y', сортировка — поPROPERTY.SORT, затемPROPERTY.ID.
Именно так делают штатные компоненты. bitrix:catalog.section наследует Bitrix\Iblock\Component\ElementList: метод initIblockPropertyFeatures() вызывает loadDisplayPropertyCodes(), тот берёт getListPageShowPropertyCodes($iblockId, ['CODE' => 'Y']) для основного инфоблока и для инфоблока торговых предложений и кладёт результат в storage['IBLOCK_PARAMS'][$iblockId]['PROPERTY_CODE'] и OFFERS_PROPERTY_CODE. Точка входа — Base::processResultData(). bitrix:catalog.element через Bitrix\Iblock\Component\Element делает то же самое, но вызывает устаревший алиас getDetailPageShowProperties().
Хранилище — ORM-класс Bitrix\Iblock\PropertyFeatureTable (таблица b_iblock_property_feature, поля PROPERTY_ID, MODULE_ID, FEATURE_ID, IS_ENABLED). Писать напрямую не нужно: есть addFeatures(), updateFeatures(), setFeatures(), все возвращают Bitrix\Main\ORM\Data\Result. CIBlockProperty::Update() сам вызывает setFeatures(), если передан ключ FEATURES.
Свой тип фичи регистрируется обработчиком события модуля iblock с полным именем Bitrix\Iblock\Model\PropertyFeature::OnPropertyFeatureBuildList. Обработчик получает параметры property и description и возвращает EventResult(EventResult::SUCCESS, [...]) с элементами MODULE_ID, FEATURE_ID, FEATURE_NAME. Эталон — Bitrix\Catalog\Product\PropertyCatalogFeature::handlerPropertyFeatureBuildList(), добавляющий IN_BASKET и OFFER_TREE.
Итог
Набор отображаемых свойств задаётся в карточке свойства и лежит в b_iblock_property_feature. Читайте его через PropertyFeature::getListPageShowPropertyCodes() / getDetailPageShowPropertyCodes() с ['CODE' => 'Y'] и проверкой на null — тогда кастомный компонент покажет ровно то же, что catalog.section.