Пользовательский тип свойства в Битрикс подключаю, когда стандартный набор - строка, число, список, файл, привязка к элементам или разделам, HTML или визуальный редактор - не закрывает задачу интерфейса или проверки данных. На практике это всплывает в карточках товаров интернет-магазинов на 1С-Битрикс: нужен цветовой пикер вместо текстового поля с HEX-кодом, маска для телефона прямо в форме создания элемента или проверка кода пункта СДЭК при сохранении свойства. Ядро трогать не нужно, в Битрикс есть официальный способ зарегистрировать свой обработчик через событие модуля iblock OnIBlockPropertyBuildList, доступное с версии 5.1.0, а не только с D7, и он переживает обновления платформы, если код лежит в правильном месте.
Когда стандартных типов свойств инфоблока не хватает
У инфоблока из коробки есть базовые типы свойств: строка, число, список, файл, привязка к элементам, привязка к разделам, HTML или визуальный редактор. Для большинства задач их достаточно - характеристики товара, ссылки на связанные материалы, картинки. Проблема начинается там, где нужно что-то из трёх вещей:
- своя разметка поля в админке - календарь с диапазоном, слайдер, цветовой пикер, карта с координатами вместо двух текстовых полей широты и долготы
- проверка значения при сохранении - маска телефона, диапазон чисел с шагом, контроль формата артикула
- преобразование значения между хранением и выводом - в базе лежит код, а в интерфейсе показывается расшифровка, подтянутая из справочника
Из практики: на проекте с доставкой через СДЭК менеджер выбирал пункт выдачи для товара с ограниченными габаритами. Хранить в свойстве голый код пункта неудобно - в списке элементов админ видит бессмысленный набор цифр вместо адреса. Кастомный тип свойства решает это одним разом: показывает название пункта в интерфейсе, а в базе хранит код, который дальше уходит в запрос при расчёте доставки.
Из чего состоит пользовательский тип свойства в Битрикс
Свой тип свойства в Битрикс это не отдельная сущность в базе, а набор PHP-функций, которые модуль iblock вызывает в нужный момент: при отрисовке поля в админке, при сохранении значения, при чтении его для компонента. Функции регистрируются одним массивом с фиксированными ключами:
GetPropertyFieldHtml- рисует поле редактирования в форме элемента в админкеGetAdminListViewHTML- как значение выглядит в списке элементов инфоблокаGetPublicViewHTMLиGetPublicEditHTML- вывод и редактирование на фронте, актуально для вебформ, завязанных на инфоблокConvertToDB- преобразует значение перед записью в базуConvertFromDB- приводит значение к рабочему виду после чтения из базыPrepareSettingsиGetSettingsHTML- отвечают за настройки самого типа, которые задаёт админ при создании свойства в инфоблоке, а не за значение в конкретном элементе
На практике из этого списка почти всегда нужны четыре: GetPropertyFieldHtml, ConvertToDB, ConvertFromDB и, если тип свойства сам по себе настраиваемый, GetSettingsHTML. Остальные можно не объявлять, Битрикс использует поведение по умолчанию.
Регистрация типа через событие OnIBlockPropertyBuildList
Модуль iblock вызывает событие OnIBlockPropertyBuildList при формировании списка доступных типов свойств, в момент открытия формы редактирования инфоблока или элемента. Обработчик должен вернуть массив с описанием, который я показывал выше.
Подписка на событие выглядит так:
<?php
use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
'iblock',
'OnIBlockPropertyBuildList',
['ColorPickerPropertyType', 'GetUserTypeDescription']
);
Куда класть код: init.php или отдельный модуль
Для одного проекта на своём стеке я бы не думал дважды, но у Битрикс своя специфика обновлений: файлы внутри /bitrix/ перезаписываются при обновлении ядра, поэтому регистрацию храню в /local/php_interface/init.php или в собственном модуле в /local/modules/. Отдельный модуль оправдан, если тип свойства переиспользуется в нескольких проектах или если в команде принято тащить кастомную логику отдельными модулями с версионированием через git.
Пример: свой тип свойства «Цвет HEX»
Возьмём случай с цветовым пикером для бейджа на карточке товара. Задача простая: в админке нативный виджет выбора цвета вместо текстового поля, в базе строка вида #ff6600.
<?php
class ColorPickerPropertyType
{
public static function GetUserTypeDescription()
{
return [
'PROPERTY_TYPE' => 'S',
'USER_TYPE' => 'ColorPicker',
'DESCRIPTION' => 'Цвет (HEX)',
'GetPropertyFieldHtml' => ['ColorPickerPropertyType', 'GetPropertyFieldHtml'],
'ConvertToDB' => ['ColorPickerPropertyType', 'ConvertToDB'],
'ConvertFromDB' => ['ColorPickerPropertyType', 'ConvertFromDB'],
];
}
public static function GetPropertyFieldHtml($property, $value, $controlName)
{
$val = htmlspecialcharsbx($value['VALUE'] ?: '#000000');
return '<input type="color" name="' . $controlName['VALUE'] . '" value="' . $val . '">';
}
public static function ConvertToDB($property, $value)
{
return ['VALUE' => $value['VALUE']];
}
public static function ConvertFromDB($property, $value)
{
$value['VALUE'] = $value['VALUE'] ?: '#000000';
return $value;
}
}
После сохранения этого файла в форме создания свойства инфоблока, там, где выбирается базовый тип «Строка», рядом появляется выпадающий список с зарегистрированными типами и в нём пункт «Цвет (HEX)». Выбираю его для нужного свойства, и в карточке товара вместо текстового поля появляется нативный color-picker браузера, без сторонних библиотек и лишнего JS на странице.
Как использовать значение на фронте и в компонентах
Для компонента, который выводит инфоблок, пользовательское свойство ничем не отличается от обычного строкового - ConvertFromDB гарантирует, что в массиве PROPERTIES всегда лежит валидный HEX, даже если поле раньше не заполняли:
<?php
$color = $arElement['PROPERTIES']['COLOR']['VALUE'];
?>
<div class="badge" style="background-color: <?= htmlspecialcharsbx($color) ?>"></div>
Бесплатный материал
🎁 Полезный скрипт в подарок
Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.
Без спама. Отписка в 1 клик.
Это и есть основная выгода от кастомного типа: логика преобразования и проверки написана один раз в классе типа, а не размазана по шаблонам компонентов, вебформам и обработчикам импорта. Понадобится, например, проверять контрастность цвета относительно фона - правится один метод ConvertToDB, и проверка сработает везде, где используется этот тип свойства, включая другие инфоблоки проекта.
Пользовательский тип свойства против других способов кастомизации
Кастомный тип свойства не единственный способ добавить нестандартную логику в инфоблок, и не всегда самый быстрый. Для разовой задачи в одном шаблоне проще написать проверку прямо в компоненте. Таблица показывает, где какой подход себя оправдывает:
| Способ | Где работает логика | Нужен код | Когда выбираю |
|---|---|---|---|
| Список значений свойства | Только в админке, значения фиксированы заранее | Не нужен | Значения известны заранее и меняются редко |
| Текст и валидация в шаблоне | Только на фронте, в конкретном шаблоне компонента | Нужен, но точечно | Разовая задача в одном месте вывода |
| Пользовательский тип свойства | В админке, на фронте и в вебформах одновременно | Нужен один раз, класс с методами | Логика нужна в нескольких инфоблоках или местах вывода |
| Highload-блок | Отдельная таблица со своими полями и записями | Нужна настройка сущности | Нужен не виджет поля, а отдельный справочник |
Если нужен не виджет для существующего свойства, а отдельная сущность вроде справочника пунктов выдачи с десятками полей и записей, это уже задача для highload-блока или отдельного инфоблока, а не для пользовательского типа свойства. Тип свойства остаётся именно виджетом одного поля, и смешивать эти два инструмента не стоит.
Если после регистрации типа нужно, чтобы кто-то сопровождал модуль через обновления платформы и версии PHP на сервере, я веду техподдержку таких доработок.
1С-Битрикс регулярно обновляется, поэтому перед внедрением я сверяюсь с актуальной документацией.
Частые вопросы
Чем пользовательский тип свойства отличается от текстового поля с проверкой на фронте?
Текстовое поле с JS-валидацией работает только там, где эта проверка явно прописана - в одном шаблоне вебформы. Пользовательский тип свойства встраивается в модуль iblock целиком: та же логика сработает и в админке при ручном заполнении, и при импорте через код, и в любом другом инфоблоке, где выбран этот тип. Разница не в сложности кода, а в том, где он переиспользуется.
Нужно ли создавать отдельный модуль, чтобы зарегистрировать свой тип свойства?
Нет, минимально достаточно /local/php_interface/init.php, Битрикс подключает этот файл при каждом хите, и событие сработает. Отдельный модуль оправдан, когда тип свойства переносится между проектами, требует своих файлов вроде JS или CSS для виджета, или когда в команде принято версионировать кастомную логику отдельно от общего init.php.
Слетают ли кастомные типы свойств при обновлении Битрикс?
Сам тип свойства не хранится в базе как отдельная сущность, при каждом хите Битрикс заново собирает список через событие OnIBlockPropertyBuildList, поэтому обновление ядра ничего не удаляет. Ломается это только если код обработчика лежит в файлах, которые перетирает обновление, то есть где-то внутри /bitrix/, поэтому регистрацию храню в /local/.
Можно ли использовать пользовательский тип свойства в вебформах и других модулях?
Да, для этого в описании типа предусмотрены GetPublicViewHTML и GetPublicEditHTML - они отвечают за вывод и редактирование значения вне админки, в том числе в модуле веб-форм, если форма привязана к инфоблоку. На практике эти колбэки нужны реже, чем связка ConvertToDB и ConvertFromDB, но для проектов с формами на фронте закрывают ту же задачу без дублирования кода.