Модуль для маркетплейс — от идеи до старта продаж. Часть 6 — база данных

Перед тем, как начать реализовывать эту часть, я решил все-таки проверить, насколько битрикс трепетно относится к структуре тех таблиц, которые сам создает. И, кажется, не зря.

Я в посте про архитектуру писал, что битрикс будет ругаться, если в одну из его таблиц добавить собственную колонку. Однако тут я немного обманул. На самом деле он проверяет наличие тех колонок, которые перечислены в инсталляторе модуля, а также их типы и настройки каждой колонки. А вот если в таблице больше колонок, чем надо, а все колонки из инсталлятора присутствуют, то битрикс никак не реагирует. Поэтому я попробую воспользоваться этой ситуацией исходя из собственных нужд. Заодно и узнаем, как к этому отнесется битрикс 🙂 А если отнесется плохо, то переделаю на пользовательские свойства, или вообще откажусь от этого механизма до поры до времени. По этому поводу добавил UPD в статью по архитектуре.

Таблица процессов

Нам понадобится таблица для хранения процессов (поначалу только для процессов генерации, но позже и для прочих процессов). Назовем таблицу maximaster_coupanda_process. Для работы с этой таблицей нам понадобится ORM сущность. Можно пойти двумя путями — сначала сделать таблицу в БД, а потом сгенерировать php код сущности, а можно наоборот, сначала написать код сущности, а потом сгенерировать таблицу. Я пойду вторым путем, т.к. битрикс будет генерировать неактуальный php-код, который сам же считает устаревшим (битрикс такой битрикс … ).

У битриксового автозагрузчика есть огромный недостаток (он не использует PSR-4). Имя файла для таблиц ORM отличается от имени класса сущности. Поэтому все классы сущностей ORM я буду складировать в отдельный неймспейс и, соответственно, в отдельную директорию. Опишем класс сущности ProcessTable и положим его в файл /lib/orm/process.php:

Все просто, понятно, и по документации. Единственное, я отошел тут от архитектуры в плане сериализации значений колонок REPORT и SETTINGS. Я планировал делать json, но битрикс довольно часто устанавливается с windows-1251 кодировкой, в которой кириллица сериализоваться в json нативным для php способом не будет. Да и к тому же в битриксе для полей сущности есть специальный флаг, который будет сам следить за необходимостью сериализации/десериализации значений. Поэтому не вижу смысла не воспользоваться нативным функционалом на данном этапе.

Но описания самой сущности недостаточно, нужно ещё эту таблицу инсталлировать/деинсталлировать. Выделим создание этой таблицы в отдельный метод и добавим вызов этого метода в InstallDB(). Для того, чтобы битрикс смог найти этот класс, нужно предварительно зарегистрировать этот модуль и подключить его:

Примерно то же самое делаем и для деинсталляции таблицы (писать код сюда не буду, оно итак понятно).

Хранение связи с ProcessTable

Теперь нам нужно добавить колонку в таблицу с купонами, которая будет ссылаться на данную таблицу. Добавить колонку в существующую таблицу довольно просто, делается это с помощью запроса ALTER_TABLE, его нужно также добавить в инсталлятор. Создаем новый метод, который добавит колонку:

И добавляем его вызов в инсталлятор.

Но тут сразу кроется засада — что если запрос на создание таблицы пройдет успешно, а запрос на добавление колонки — нет? Или наоборот, запрос на создание таблицы не пройдет, а на создание колонки — прокатит? Добавлять кучу проверок на этот счет? Нафиг, сразу лучше использовать транзакции.

Кроме этого нужно какую-то ошибку показывать пользователю, если вдруг инсталляция не удалась. Сделаем пока простую заглушку, которая тупо будет транслировать сообщение из словленного исключения в процессе инсталляции БД.

В результате наш метод инсталляции БД превращается в нечто такое:

Примерно то же самое опишем в методе деинсталляции БД, но в немного другом порядке (снятие регистрации модуля оставляем в конце, после того как все данные удалены успешно):

По хорошему, нужно обработать каждый тип исключения, который выбрасывается битриксом при выполнении работы с БД, и обработать каждую ошибку по разному. Но мы же делаем MVP, а значит отложим это до момента запуска проекта, т.к. частота появления ошибки будет слишком низкой, а полученной информации чаще всего будет достаточно для того, чтобы разработчики смогли разобраться с проблемой инсталляции.

Проверяем

После инсталляции модуля с нуля тестируем наличие новой таблицы:

Добавим запись:

Проверим, корректно ли была выполнена связь между таблицами:

Данные из связанной таблицы выводятся корректно.

В процессе написания этой статьи стало понятно, что для работы с колонками SETTINGS и REPORT будет гораздо удобнее использовать объекты. Для этого потребуется добавить в класс сущности валидацию этих полей с помощью механизов ORM. В методе getMap для каждого из этих полей добавляем настройку validation, которая должна содержать коллбек, возвращающий массив валидаторов:

а также добавим методы валидации:

Теперь, при создании и обновлении записей в БД битрикс будет использовать эти валидаторы, у благодаря сериализации/десериализации мы сможем хранить эти данные в БД и получать из БД готовый заполненный инстанс нужного класса.

Подводим итоги.

Я не претендую на экспертность по части БД, возможно я тут накосячил. Напишите мне в комментах, если вдруг где-то тут есть серьезные огрехи, буду исправлять.

В этой статье я создал небольшой реальный пример связки модуля Битрикс с БД и все минимально необходимое для этого. Осталось узнать, как на эти изменения отреагирует сам битрикс при проверке модуля 🙂

В следующей статье я начну реализовывать основную часть логики — сами классы генераторов, последовательностей, проверку зависимостей и может быть начну заниматься внешним видом.