Блог Горошко Андрея 1C-Битрикс Создание своей ORM-сущности в Битрикс: DataManager и getMap с нуля

Создание своей ORM-сущности в Битрикс: DataManager и getMap с нуля

Средний рейтинг
Еще нет оценок

D7 ORM позволяет работать не только со стандартными сущностями (ElementTable, UserTable), но и описывать свои собственные для любых таблиц в базе данных.

Это позволяет получить все преимущества ORM (удобные выборки, объекты, события, валидацию) для ваших кастомных данных, делая код чистым и типизированным.

Задача: Создадим ORM-сущность для таблицы my_company_reviews (отзывы).

Шаг 0: Подготовка таблицы в Базе Данных

Прежде всего, нам нужна сама таблица в БД. Создадим ее с помощью SQL-запроса.

CREATE TABLE my_company_reviews (
    ID INT PRIMARY KEY AUTO_INCREMENT,
    AUTHOR_NAME VARCHAR(255) NOT NULL,
    RATING INT NOT NULL,
    COMMENT TEXT NULL,
    DATE_CREATED DATETIME NOT NULL,
    CREATED_BY INT NULL
);

Мы добавили поле CREATED_BY для будущей связи с таблицей пользователей.

Шаг 1: Файловая структура и автозагрузка

Все ORM-сущности должны располагаться в папке lib вашего модуля.

Название файла и класса должно соответствовать стандарту [EntityName]Table.php.

  1. Создайте файл: /local/modules/my.module/lib/ReviewTable.php.
  2. Настройте автозагрузку. Убедитесь, что пространство имен My\Module зарегистрировано в composer.json вашего проекта или в include.php вашего модуля.codePHP// /local/modules/my.module/include.php \Bitrix\Main\Loader::registerAutoLoadClasses( 'my.module', [ 'My\\Module\\ReviewTable' => 'lib/ReviewTable.php', ] );

Шаг 2: Создание класса-наследника DataManager

Класс сущности должен наследоваться от абстрактного класса \Bitrix\Main\Entity\DataManager.

// /local/modules/my.module/lib/ReviewTable.php
namespace My\Module;

use Bitrix\Main\Entity;
use Bitrix\Main\Type;
use Bitrix\Main\UserTable; // Подключаем сущность пользователей для связи

class ReviewTable extends Entity\DataManager
{
    /**
     * Возвращает физическое имя таблицы в базе данных.
     * @return string
     */
    public static function getTableName()
    {
        return 'my_company_reviews';
    }

    // Здесь будет метод getMap()
}

Шаг 3: Описание карты полей (getMap) — Сердце сущности

Метод getMap() — самый важный.

Он «объясняет» ORM, из каких полей состоит ваша таблица, какие у них типы, какие являются первичными ключами, какие правила валидации к ним применять и как они связаны с другими таблицами.

/**
 * Возвращает описание полей сущности.
 * @return array
 */
public static function getMap()
{
    return [
        // ID: Целое число, первичный ключ, автоинкремент
        (new Entity\IntegerField('ID'))
            ->configurePrimary()
            ->configureAutocomplete(),

        // Имя автора: Строка, обязательное, с валидацией длины
        (new Entity\StringField('AUTHOR_NAME', [
            'validation' => function() {
                return [
                    new Entity\Validator\Length(2, 50),
                ];
            }
        ]))
            ->configureRequired()
            ->configureTitle('Имя автора'),

        // Рейтинг: Целое число, с валидацией диапазона
        (new Entity\IntegerField('RATING', [
            'validation' => function() {
                return [
                    new Entity\Validator\Range(1, 5),
                ];
            }
        ]))
            ->configureRequired()
            ->configureTitle('Рейтинг'),

        // Комментарий: Текстовое поле
        (new Entity\TextField('COMMENT'))
            ->configureTitle('Текст отзыва'),

        // Дата создания: Дата/время, со значением по умолчанию
        (new Entity\DatetimeField('DATE_CREATED'))
            ->configureDefaultValue(new Type\DateTime())
            ->configureTitle('Дата создания'),

        // ID создателя: Целое число
        (new Entity\IntegerField('CREATED_BY'))
            ->configureTitle('Кем создан'),
            
        // Связь с пользователем (ReferenceField)
        (new Entity\ReferenceField(
            'AUTHOR', // Псевдоним для этой связи
            UserTable::class, // Класс сущности, с которой связываемся
            ['=this.CREATED_BY' => 'ref.ID'] // Условие JOIN ON
        ))
    ];
}

Разбор getMap():

  • Новый синтаксис (чейнинг): Вместо передачи всех параметров в конструктор, можно использовать методы configure*(). Это делает код более читаемым.
  • configurePrimary() и configureAutocomplete(): Удобные методы для настройки первичного ключа.
  • configureRequired(): Делает поле обязательным.
  • configureTitle(): Задает человекопонятное название поля (используется, например, в административных интерфейсах).
  • ReferenceField: Это ключ к связям!
    • AUTHOR: Псевдоним, по которому мы будем обращаться к связанному пользователю.
    • UserTable::class: Сущность, к которой мы «присоединяемся».
    • [‘=this.CREATED_BY’ => ‘ref.ID’]: Условие JOIN. this — это наша текущая таблица (ReviewTable), ref — это таблица, к которой присоединяемся (UserTable).

Шаг 4 (Опционально): Метод getUfId()

Если вы планируете добавлять к вашей сущности пользовательские поля (UF-поля) через стандартный интерфейс Битрикс, необходимо реализовать этот метод.

/**
 * Возвращает ID для пользовательских полей (UF).
 * @return string
 */
public static function getUfId()
{
    return 'MY_REVIEW';
}

Это ID должен быть уникальным в рамках всей системы.

Шаг 5: Использование новой сущности

Теперь ваша сущность готова к работе. Вы можете использовать все методы D7 ORM.

use My\Module\ReviewTable;

// Добавляем отзыв
$result = ReviewTable::add([
    'AUTHOR_NAME' => 'Иван',
    'RATING' => 5,
    'COMMENT' => 'Все отлично!',
    'CREATED_BY' => 1, // ID текущего пользователя
]);

// Получаем отзывы с именами их авторов
$reviews = ReviewTable::getList([
    'select' => [
        'ID',
        'RATING',
        'AUTHOR_NAME',
        // Обращаемся к полю связанной сущности через псевдоним
        'AUTHOR_LOGIN' => 'AUTHOR.LOGIN'
    ],
    'filter' => ['>=RATING' => 4],
])->fetchAll();

print_r($reviews);
/*
Вывод:
[
    [
        'ID' => 1,
        'RATING' => 5,
        'AUTHOR_NAME' => 'Иван',
        'AUTHOR_LOGIN' => 'admin'
    ]
]
*/

Бонус: Создание таблицы из ORM-описания

Если у вас еще нет таблицы в БД, вы можете создать ее на основе вашего getMap().

use Bitrix\Main\Application;

$entity = ReviewTable::getEntity();
$tableName = ReviewTable::getTableName();
$connection = Application::getConnection();

// Проверяем, существует ли таблица
if (!$connection->isTableExists($tableName)) {
    // Создаем таблицу
    $entity->createDbTable();
}

Этот код удобно размещать в методе DoInstall() вашего модуля.

Вывод:
Создание собственных DataManager-классов — это фундаментальный навык для современной разработки на Битрикс.

Это позволяет инкапсулировать всю логику работы с кастомной таблицей в одном месте, получить все преимущества ORM (включая события, валидацию и связи) и сделать код чистым, типизированным и легко поддерживаемым.

D7 ORM, DataManager, getMap, своя ORM сущность, создать таблицу Битрикс, IntegerField, StringField, ReferenceField, Validator, Битрикс разработка.

Мой рейтинг:

Добавить комментарий

Related Post

Современная работа с разделами инфоблоков: SectionTable::getList в Bitrix D7 ORMСовременная работа с разделами инфоблоков: SectionTable::getList в Bitrix D7 ORM

Средний рейтинг Еще нет оценок Продолжая осваивать D7 ORM, перейдем от элементов к разделам. Для работы с разделами инфоблоков в современном API предназначен класс \Bitrix\Iblock\SectionTable. Он предоставляет тот же мощный и

Гибкая выборка в D7 ORM: Мастер-класс по классу QueryГибкая выборка в D7 ORM: Мастер-класс по классу Query

Средний рейтинг Еще нет оценок Хотя статический метод ::getList() удобен для простых выборок, его возможности ограничены, когда условия запроса нужно формировать динамически. Для таких задач в D7 ORM существует специальный класс-конструктор — \Bitrix\Main\Entity\Query.

Управление файлами в Битрикс с помощью CFile: Сохранение, ресайз и удалениеУправление файлами в Битрикс с помощью CFile: Сохранение, ресайз и удаление

Средний рейтинг Еще нет оценок Работа с файлами — неотъемлемая часть веб-разработки. В Битрикс для этого существует мощный класс CFile. Он не просто работает с файлами на диске, но и регистрирует