Зачем нужны кастомные типы пользовательских свойств
В 1С-Битрикс пользовательские свойства (UF-поля) — это мощный инструмент для расширения сущностей: пользователей, элементов инфоблоков, заказов и других объектов. Стандартный набор типов включает строку, число, список, файл, дату и несколько других. Но практика показывает, что этого часто недостаточно.
Например, вам может потребоваться поле «Название и описание» — составное поле, хранящее два значения в одном свойстве. Или поле с цветовым выбором, поле с координатами на карте, поле с JSON-структурой. Для таких случаев Битрикс предоставляет механизм регистрации кастомных типов пользовательских свойств через событие OnIBlockPropertyBuildList.
Структура класса кастомного типа свойства
Кастомный тип свойства реализуется как PHP-класс со статическими методами. Минимально необходимые методы:
- GetUserTypeDescription() — описание типа: идентификатор, название, привязка методов.
- GetPropertyFieldHtml() — HTML для редактирования значения в административной панели.
- ConvertToDB() — сериализация значения перед записью в базу данных.
- ConvertFromDB() — десериализация значения при чтении из базы данных.
- GetPublicViewHTML() — отображение значения на публичной части сайта.
Дополнительно можно реализовать методы для фильтрации, вывода в списке элементов, настроек свойства и т.д.
Регистрация типа в системе
Тип регистрируется через подписку на событие OnIBlockPropertyBuildList. Это событие собирает все доступные типы свойств при каждом обращении к списку типов в системе.
|
1 2 3 4 |
<?php use Bitrix\Main\EventManager; $eventManager = EventManager::getInstance(); $eventManager->addEventHandler("iblock", "OnIBlockPropertyBuildList", "CIBlockNewProperty_TitleDescr::GetUserTypeDescription"); |
Метод GetUserTypeDescription() должен возвращать массив с описанием типа, где USER_TYPE — уникальный строковый идентификатор вашего типа, PROPERTY_TYPE — базовый тип хранения в БД (S для строки, N для числа, F для файла).
Полный пример класса: составное свойство «Название и значение»
Ниже — полный рабочий код класса для кастомного типа свойства, хранящего пару «название + описание» в одном поле:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
<?php use Bitrix\Main\EventManager; $eventManager = EventManager::getInstance(); $eventManager->addEventHandler("iblock", "OnIBlockPropertyBuildList", "CIBlockNewProperty_TitleDescr::GetUserTypeDescription"); class CIBlockNewProperty_TitleDescr { public static function GetUserTypeDescription() { return array( "PROPERTY_TYPE" => "S", "USER_TYPE" => "DESCRIPTION_LIST", "DESCRIPTION" => "Название и значение", "GetPropertyFieldHtml" => array(__CLASS__, "GetPropertyFieldHtml"), "ConvertToDB" => array(__CLASS__, "ConvertToDB"), "ConvertFromDB" => array(__CLASS__, "ConvertFromDB"), "GetPublicViewHTML" => array(__CLASS__, "GetPublicViewHTML"), ); } public static function GetPropertyFieldHtml($arProperty, $value, $strHTMLControlName) { // Убедитесь, что $value["VALUE"] это массив if (is_string($value["VALUE"])) { $value["VALUE"] = unserialize($value["VALUE"]); // Распакуйте значения, если это строка } $html = '<div style="min-width: 160px; display: inline-block;">Название:</div>'; $html .= '<input type="text" style="min-width: 250px; margin-bottom: 5px;" name="'.$strHTMLControlName["VALUE"].'[title]" value="'.htmlspecialchars($value["VALUE"]['title']).'"><br>'; $html .= '<div style="min-width: 160px; display: inline-block; vertical-align: top;">значение:</div>'; $html .= '<textarea style="min-width: 290px; vertical-align: top;" name="'.$strHTMLControlName["VALUE"].'[description]">'.htmlspecialchars($value["VALUE"]['description']).'</textarea><br><br><br>'; return $html; } public static function ConvertToDB($arProperty, &$arValue) { if (isset($arValue['VALUE']) && !empty($arValue['VALUE'])) { if (empty($arValue['VALUE']["title"]) || empty($arValue['VALUE']["description"]) ) { return array('VALUE' => null); } $arValue['VALUE'] = serialize($arValue['VALUE']); // Используем serialize вместо json_encode для совместимости return $arValue; } return array('VALUE' => null); } public static function ConvertFromDB($arProperty, &$arValue) { if ($arValue['VALUE']) { $arValue['VALUE'] = unserialize($arValue['VALUE']); } return $arValue; } public static function GetPublicViewHTML($arProperty, $value, $strHTMLControlName) { if (!is_array($value["VALUE"])) { $value = static::ConvertFromDB($arProperty, $value); } if (!empty($value["VALUE"])) { $output = ''; foreach ($value["VALUE"] as $item) { $title = htmlspecialchars($item['title'] ?? ''); $description = htmlspecialchars($item['description'] ?? ''); $output .= "<strong>{$title}</strong><br>{$description}<br>"; } return $output; } else { return null; } } } ?> |
Разбор методов класса
GetPropertyFieldHtml — генерирует HTML-форму для редактирования свойства в административной панели. Параметр $strHTMLControlName["VALUE"] содержит имя поля формы, которое Битрикс использует для сбора значений. Важно формировать имена полей как массив: name="fieldname[title]" и name="fieldname[description]".
ConvertToDB — преобразует значение перед сохранением. В данном примере массив сериализуется функцией serialize(). Метод также отвечает за валидацию: если оба поля пусты, возвращается null.
ConvertFromDB — обратная операция: десериализует строку из базы данных обратно в массив при чтении.
GetPublicViewHTML — отвечает за вывод значения на публичной части. Если данных нет, возвращает null.
Подключение файла класса
Файл с классом и регистрацией события размещается в:
|
1 |
/local/php_interface/init.php |
Либо выносится в отдельный файл и подключается из init.php:
|
1 2 |
// В /local/php_interface/init.php require_once $_SERVER['DOCUMENT_ROOT'] . '/local/php_interface/classes/CIBlockNewProperty_TitleDescr.php'; |
Второй подход предпочтителен для крупных проектов: каждый кастомный тип свойства хранится в отдельном файле, что упрощает поддержку кода.
Тестирование: как проверить что тип появился
После добавления кода в init.php выполните следующие шаги:
- Перейдите в административную панель: Контент → Инфоблоки → Типы инфоблоков, выберите любой инфоблок и откройте раздел Свойства.
- Нажмите «Добавить свойство» и в поле Тип найдите «Название и значение» (или то описание, которое вы указали в
DESCRIPTION). - Если тип отображается в списке — регистрация прошла успешно.
- Создайте свойство данного типа, добавьте элемент инфоблока и заполните поля — убедитесь, что данные сохраняются и отображаются корректно.
- Если тип не появляется, проверьте наличие синтаксических ошибок в PHP-файле командой:
php -l /local/php_interface/init.php.
