Приступим к созданию собственных сущностей для проекта. Я немного расскажу про датаменеджер, продемонстрирую какие шаги я предпринимаю для создания таблиц и познакомлю с небольшим сервисом для генерации классов.
Говоря слово «сущность», я подразумеваю некий объект с определенным набором свойств, связей и событий. Я предпочитаю не использовать инфоблоки и смарт процессы для решения подобного класса задач, так как считаю этот функционал немного избыточным и не всегда уместным. Меня вполне устраивают обычные таблицы и DataManager, позволяющий выполнять основные операции.
Приступаем к работе.
Шаг 1 Поля сущности
Начнём с описания сущности «Издание» — это ключевая фигура нашего проекта, группирующая экземпляры книг. Предположим мы выяснили, что каждый объект должен хранить в себе информацию о годе выпуска, издательстве и авторе, а также название, обложку, жанр и описание.
Получаем схему следующего вида:
Название | Код | Тип | Обязательно | Примечание |
Идентификатор | ID | число | да | первичный ключ |
Название | NAME | строка | да | |
Год издания | PUBLISHING_YEAR | число | да | |
Издательство | PUBLISHING_HOUSE | строка | да | |
Автор | AUTHOR | строка | да | |
Жанр | GENRE | строка | нет | |
Описание | DESCRIPTION | текст | нет | |
Обложка | BOOK_COVER_ID | число | нет | идентификатор файла |
Сразу можно обратить внимание на то, что некоторые поля являются справочными, а некоторые можно вынести в отдельные сущности. Например, Издательство и авторы вполне могут содержать какую-то дополнительную информацию, а жанры — это самый что ни на есть справочник. Всё это мы обязательно разделим и сделаем, но позже. Сейчас я показываю как создать сущность на простеньком примере.
Шаг 2 Описание сущности
В минимальном представлении, описание сущности состоит из двух методов, которые возвращают название таблицы в базе данных
public static function getTableName() { return 'table_name'; }
и список полей сущности
public static function getMap() { return [ // ... поля ... ]; }
Каждое поле является экземпляром класса конкретного типа, наследуемого от базового класса Bitrix\Main\Entity\Field. У объектов данных типов есть методы, которые устанавливают аттрибуты полей
- configurePrimary() — первичный ключ
- configureAutocomplete() — автоинкремент
- configureRequired() — обязательность
- и другие (со всеми методами можно ознакомиться в классе Bitrix\Main\ORM\Fields\ScalarField)
Класс самой сущности должен заканчиваться суффиксом Table и является наследником датаменеджера
class EditionTable extends \Bitrix\Main\Entity\DataManager { //... }
Для начала этих знаний хватит чтобы собрать класс нашей сущности. Где и как я предпочитаю размещать классы я рассказывал в этой статье.
<?php namespace Aclips\BookRental\Internal; use Bitrix\Main\ORM\Data\DataManager; use Bitrix\Main\ORM\Fields\IntegerField; use Bitrix\Main\ORM\Fields\StringField; use Bitrix\Main\ORM\Fields\TextField; class EditionTable extends DataManager { public static function getTableName() { return "a_bookrental_editions"; } public static function getMap() { return [ (new IntegerField('ID')) ->configurePrimary() ->configureAutocomplete(), (new StringField('NAME')) ->configureRequired(), (new IntegerField('PUBLISHING_YEAR')) ->configureRequired(), (new StringField('PUBLISHING_HOUSE')) ->configureRequired(), (new StringField('AUTHOR')) ->configureRequired(), (new StringField('GENRE')), (new TextField('DESCRIPTION')), (new IntegerField('BOOK_COVER_ID')), ]; } }
Шаг 3 Создание таблицы в базе данных
Здесь всё просто. Для создания таблицы в бд нужно вызвать метод createDBTable на объекте сущности.
$entity = \Aclips\BookRental\Internal\EditionTable::getEntity(); $entity->createDBTable();
Для удобства я использую консольную утилиту, которая проверяет на существование таблицы сущностей и добавляет их в базу при отсутствии. Скрипт выглядит примерно так
<?php /** * Консольная утилита для проверки существования и создание таблиц сущностей в бд * * Пример запуска: * /usr/bin/php -f ~/www/local/php_interface/install/db_tables.php **/ if (php_sapi_name() != 'cli') { die(); } // Абсолютный путь к корневой директории проекта $_SERVER['DOCUMENT_ROOT'] = '/home/bitrix/www'; // Отключение ненужных проверок и действий define("NO_KEEP_STATISTIC", true); define("NOT_CHECK_PERMISSIONS", true); define("NEED_AUTH", true); require_once($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/main/include/prolog_before.php"); // Классы сущностей проекта для создания таблиц в бд $dataManagerClasses = [ \Aclips\BookRental\Internal\EditionTable::class, // ... ]; foreach ($dataManagerClasses as $dataManagerClass) { try { // Получение объекта сущности $entity = $dataManagerClass::getEntity(); // Получение названия таблицы бд $tableName = $entity->getDBTableName(); // Проверка на отсутствие таблицы в бд if (!$connection->isTableExists($tableName)) { // Создание бд $result = $entity->createDBTable(); // log: Table $tableName created successfully } else { // log: Table $tableName already exists } } catch (\Throwable $e) { // log: Exception $e->getMessage() } }
Запуск скрипта
/usr/bin/php -f ~/www/local/php_interface/install/db_tables.php
При желании можно добавить логирование результата выполнения или отображение в консоли
fwrite(STDOUT, 'Вывод сообщения в консоль'.PHP_EOL);
Бонус
Для ускорения описания полей сущностей я сделал небольшой (надеюсь) интуитивно понятный сервис. На момент написания статьи в нём нельзя указать реляции и доступны только базовые типы полей, тем не менее позволяет экономить время. Да, bitrix24 позволяет генерировать классы сущностей из коробки, но меня это не устраивает по двум причинам, так как для этого в базе данных уже должна существовать таблица, а создавать её sql запросом или через другие инструменты я не хочу.
Бонус временно недоступен 🙂
Думаю, что для начала этой информации достаточно для понимания общей концепции и принципа работы. В следующей статье я продолжу работу над проектом, создам недостающие сущности и расскажу про работу с сущностями через EntityManager.