how we created custom user fields in Bitrix

Hello, this is Dima, backend developer from Hawking Bros. Today I will talk about solving the problem that we encountered when implementing non-standard infoblock logic on a project with Bitrix multisite.

This article will be useful for developers who are setting up Bitrix and want to learn more about its capabilities. If you want to skip the introduction to basic setup, feel free to scroll down to the Personal Experience section.

Creating Custom Property Types

An information block (infoblock) is a kind of entity for storing information of any block on the site. It is used to store standard information for site blocks: title, id, preview text, preview image, etc. Infoblocks contain standard write fields that cover most of the use cases. For other cases, you will need this article 🙂

A new property can be created in a few simple steps:

  1. Come up with a name and character code for the property.

  2. Select required property type – they are basic and custom. Custom ones help in solving specific tasks: linking to Yandex Map, or blocks on the site to user types.

  3. Select whether this property is plural or not. For example, adding several images for a product card is implemented through this parameter.

  4. Set additional options in the advanced editor if necessary.

There are situations when basic types are not enough to implement a certain business logic: the schedule of classes with a trainer, the time of appointment with doctors. That’s where custom property types come in. The difficulty is that there is no simple tool for such settings, and this is implemented through code.

To create a new type of property, it is necessary in the file init.php add an event listener OnIBlockPropertyBuildList from the iblock module and write a handler for this event as a class with a function GetUserTypeDescription, which returns an array with property type information. It’s good practice to put the listener logic in a separate events.php file, which is then included in the init.php file, so as not to clutter one file with a huge amount of logic.

The required elements are:

  1. USER_TYPE_ID – unique identifier of the property type.

  2. USER_TYPEcharacter code of the property type.

  3. CLASS_NAME – the name of the class that implements the logic of the property type (most often, this method and the logic of the property are located in the same class, but you can separate them into different ones).

  4. DESCRIPTION – property type name that will be displayed in the administrative panel.

  5. PROPERTY_TYPE – the type of the base property from which the standard logic for working with the property is inherited.

An example of such a function:

public function GetUserTypeDescription(): array
    {
        return [
            'USER_TYPE_ID' => 'schedule',                                  //Уникальный идентификатор типа свойств
            'USER_TYPE' => 'SCHEDULE',                                     // Символьный код типа свойств
            'CLASS_NAME' => __CLASS__,                                     // Название класса, который реализует логику типа свойств
            'DESCRIPTION' => 'Расписание',                                 // Название свойства, которое будет отображаться в административной панели
            'PROPERTY_TYPE' => Bitrix\Iblock\PropertyTable::TYPE_STRING,   // Тип базового свойства, от которого будет браться стандартная логика работы с данным свойством
        ];
    }

The created property type will appear in the admin panel, but will be displayed empty – as there is no implemented method for displaying a property with a custom type.

Let’s move on to creating the method:

  • Implementing the Method GetPropertyFieldHtml in the class whose name is specified in the field CLASS_NAME. It must be in the array returned by the method GetUserTypeDescription.

  • Let’s add a field of the form to the array:
    'GetPropertyFieldHtml' => [CLASS, 'GetPropertyFieldHtml'].

  • In the created method, we will form a property mapping with the described property type and return it as the result of the function operation (as a string).

Additional parameters for the GetUserTypeDescription array

Consider other parameters for the array GetUserTypeDescriptionthat may come in handy at work:

  1. CheckFields – the method must check the correctness of the property value and return an array. Empty if there are no errors, and with error messages if there are.

  2. GetUIFilterProperty – the method describes the type of the filtering field in the main.ui.filter component on the administrative pages of infoblocks.

  3. GetLength – the method must return the actual length of the property value. It is needed only for properties whose values ​​are complex structures (for example, an array).

  4. ConvertToDB – The method must convert the property value into a format suitable for storing in the database. And return an array of the form array("VALUE" => "...", "DESCRIPTION" => "...").
    If the property value is an array, then it would be reasonable to use the function serialize. But the Date/Time is converted to the ODBC format “YYYY-MM-DD HH:MI:SS”. This will determine the sorting and filtering options for the values ​​of this property.

  5. ConvertFromDB – The method must convert the property value from a database-storable format to a processing format. And return an array of the form array("VALUE" => "...", "DESCRIPTION" => "..."). Complements ConvertToDB.

  6. GetPropertyFieldHtmlMulty – Displaying the form for editing a multiple property. If absent, then GetPropertyFieldHtml is used for each value separately (for multiple properties).

  7. GetAdminListViewHTML – The method returns the safe HTML display of the property value in the list of elements of the administrative part.

  8. GetPublicViewHTML – The method must return a secure HTML display of the property value in the public part of the site. If it returns an empty value, then the value will not be displayed.

  9. GetPublicEditHTML – The method should return the HTML display of the control for editing property values ​​in the public part of the site.

  10. GetSettingsHTML – The method returns safe HTML for displaying property settings for the infoblock editing form.

  11. PrepareSettings – The method returns either an array with additional property settings, or the entire set of settings, including the standard ones.

Personal experience setting custom property types

On the project for an online store of building materials, the implementation of multi-city using Bitrix multi-site is conceived: one city – one physical site.
Our team was faced with the task of implementing the division of content between sites in order to create unique content for different cities, as well as to use the already created content on several sites.

We decided to do this with the help of a property in infoblocks, which would allow selecting several sites for one entry. At the same time, we had several limitations: the absence of a property for displaying a list of sites in the infoblock, and a ban on adding sites manually through the “List” property.

So we came to the need to create our own custom property type, which will pull all sites through the Bitrix API and display them in the form of a regular list.

The first problem arose when saving the selected results. In my custom property type, I specified:

'PROPERTY_TYPE' => Iblock</span>PropertyTable::TYPE_LIST, because the property looks like a standard list, just with auto-populated values. It didn’t work, and the selected property values ​​didn’t reach the database.

Searching open sources and working with the kernel led me to the fact that it is not enough for a property of type list to simply print the entire list of values. It was also necessary to write them to the database in a separate table for all Enum of all properties of the list type, which happens under the hood of Bitrix with normal manual filling. I did not find the best way to do this, so I resorted to an alternative.

I replaced PROPERTYTYPE on the Iblock</span>PropertyTable::TYPESTRINGwhich made it possible to store in the database just the names of sites, and not their ENUM_ID from the table of field values ​​of the property of type list.

Since it was required to provide logic for multiple selection of sites in 1 element, I chose the “Multiple” property, but instead of compactly outputting my table with multiple selection of values ​​​​- as it usually works in the standard property of the List type – I displayed a table many times with an opportunity in each of choose only one value.

After a long search in the Core, I found what I was looking for: checking for the existence in the array of the description of the type of the field property with a link to the method for unique layout when the multiple property is selected.
To make a unique layout for displaying a multiple property for a custom type, it is necessary in the result of the method GetUserTypeDescription add field 'GetPropertyFieldHtmlMulty' => [CLASS, 'GetPropertyFieldHtmlMulty']and also implement the method 'GetPropertyFieldHtmlMulty' with the body in which the display for the multiple property will be formed.

I share the final version in the screenshot:

This is how it looks in the administrative panel - available sites are displayed in the list
This is how it looks in the administrative panel – available sites are displayed in the list

I hope this article was helpful to you! I will be glad if you share your stories in the comments.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *