Структура модуля
Готовый код можно скачать в моем репозитории на GitFlic.
В интернете есть много информации по архитектуре D7, но мало практической информации как организовать код, какие новые возможности мы можем использовать на практике и для чего. В данной статье я опишу о том как создать модуль на D7 с компонентом. Сборка содержит почти всё, что может пригодиться при разработке своих решений, каждый шаг описан множеством комментариев. Сделано с целью иметь готовый модуль болванку с подробным описанием для быстрого применения на практике.
Что умеет сборка
При установке:
- Установка модуля в один и несколько этапов
- Создание таблиц, описанных с помощью ORM-сущностей
- Установка агента
- Установка событий
- Копирование файлов компонента и для административной части
- Наполнение таблиц тестовыми данными
- Описание прав доступа к модулю
При удалении:
- Удаление модуля в один и несколько этапов с предложением сохранить существующие данные
- Удаление таблиц, описанных с помощью ORM-сущностей
- Удаление агентов
- Удаление событий
- Удаление файлов компонента и административной части
Что реализовано интересного:
- Описанны ORM-сущности, две таблицы для примера работы связей, одна связана с другой
- Пример класса агента модуля и метода для выполнения, который регистрируется и начинает выполняться при установке
- Примеры событий, одно из них реализовано в ORM-сущности, второе при установке
- Описанная страница настроек модуля для административной части с тестовыми параметрами и их сохранением, включающая вкладку редактирования прав
- Примеры компонентов, работающих с разными технологиями и ORM-сущностью
Виды модулей
Системные модули распологаются в папке /bitrix/modules/
и мы их не трогаем.
Собственные модули распологаются в папке /local/modules/
. В качестве названия корневой папки модуля, может выступать любое не занятое название, но при этом есть свои особенности.
Расположение модуля в админке
Мы можем расположить свой модуль в двух местах админки.
Системные модули
Страница установки системных модулей находится в Настройки -> Настройки продукта -> Модули
:
В этом случае название корневой папки модуля пишется одним словом, например:
hmarketing
В этом случае название класса в файле /local/modules/hmarketing/install/index.php
будет class hmarketing extends CModule
.
Партнерские модули
Если название вашего модуля написан через точку, модуль считается партнёрским и его местоположение будет другое Marketplace -> Установленные решения
:
Такой модуль требует специфического названия состаящего из:
- Кода партнера
- Названия модуля
код_партнёра.название_модуля
В этом случае название корневой папки модуля пишется двумя словами, например hmarketing.d7
, название класса в файле /local/modules/hmarketing.d7/install/index.php
будет class hmarketing_d7 extends CModule
.
Структура
- Папка
hmarketing.d7
-
Папка
admin
- Файл
menu.php
расположение модуля в меню админки Битрикс - Файл
hmarketing.php
админка для пользователей Битрикс без прав администратора, нужно самим создавать ORM для записи в БД
- Файл
-
Папка
install
-
Папка
admin
- Файл
hmarketing.php
файл который будет скопирован в дирикториюbitrix
и будет инклудить админку для пользователей Битрикс без прав администратора
- Файл
-
Папка
components
содержит свой компонент для установки в Битрих путем копирования -
Папка
files
- Файл
hmarketing.php
файл который будет скопирован в дирикториюосновной файл установки
- Файл
instalInfo-step1.php
установка модуля в несколько шагов (1-й шаг) - Файл
instalInfo-step2.php
установка модуля в несколько шагов (2-й шаг) - Файл
instalInfo.php
установка модуля в один шаг - Файл
deInstalInfo-step1.php
удаление модуля в несколько шагов (1-й шаг) - Файл
deInstalInfo-step2.php
удаление модуля в несколько шагов (2-й шаг) - Файл
deInstalInfo.php
удаление модуля в один шаг - Файл
version.php
файл с версией и датой выхода модуля
- Файл
-
Папка
lang
-
Папка
ru
-
Папка
lib
- Файл
data.php
языковой файл базы данных
- Файл
-
Папка
install
- Файл
index.php
языковой файл установки - Файл
instalInfo-step1.php
языковой файл вывода сообщения в админке сайта при установке модуля в несколько шагов (1-й шаг) - Файл
instalInfo-step2.php
языковой файл вывода сообщения в админке сайта при установке модуля в несколько шагов (2-й шаг) - Файл
instalInfo.php
языковой файл вывода сообщения в админке сайта при установке модуля - Файл
deInstalInfo-step1.php
языковой файл вывода сообщения в админке сайта при удаление модуля в несколько шагов (1-й шаг) - Файл
deInstalInfo-step2.php
языковой файл вывода сообщения в админке сайта при удаление модуля в несколько шагов (2-й шаг) - Файл
deInstalInfo.php
языковой файл вывода сообщения в админке сайта при удалении модуля
- Файл
-
Папка
-
Папка
-
Папка
lib
- Файл
Agent.php
класс агента - Файл
Author.php
вспомогательная таблица модуля написанная через ORM - Файл
Data.php
основная таблица модуля написанная через ORM - Файл
Events.php
класс события - Файл
Main.php
основной класс модуля
- Файл
- Файл
include.php
используется для подключения файлов модуля - Файл
options.php
настройки модуля в админке с правами администратора, Битрикс сам создает записи в БД
Файл /admin/menu.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Данный файл создаёт пункты меню в административном интерфейсе Битрикс, дефолтные настройки:
В файле небходимо создать массив
$aMenu
, в котором указываются параметры меню, полный состав массива можно посмотреть на официальном сайте.local/modules/hmarketing.d7/admin/menu.php
<? defined('B_PROLOG_INCLUDED') and (B_PROLOG_INCLUDED === true) or die(); // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // сформируем верхний пункт меню $aMenu = array( // пункт меню в разделе Контент 'parent_menu' => 'global_menu_services', // сортировка 'sort' => 1, // название пункта меню 'text' => "Модули Эйч Маркетинг", // идентификатор ветви "items_id" => "menu_webforms", // иконка "icon" => "form_menu_icon", ); // дочерния ветка меню $aMenu["items"][] = array( // название подпункта меню 'text' => 'Страница модуля', // ссылка для перехода 'url' => 'hmarketing.php?lang=' . LANGUAGE_ID ); // дочерния ветка меню $aMenu["items"][] = array( // название подпункта меню 'text' => 'Админка модуля', // ссылка для перехода 'url' => 'settings.php?lang=ru&mid=hmarketing.d7' ); // возвращаем основной массив $aMenu return $aMenu;
Файл /admin/hmarketing.php
Файл добаввляется в дирикторию
bitrix
и вызывается при переходе в админки.Данный файл создаёт пункты меню в административном интерфейсе Битрикс, дефолтные настройки:
local/modules/hmarketing.d7/admin/hmarketing.php
<? require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php'; // пространство имен для автозагрузки модулей use \Bitrix\Main\Loader; // получим права доступа текущего пользователя на модуль $POST_RIGHT = $APPLICATION->GetGroupRight("hmarketing.d7"); // если нет прав - отправим к форме авторизации с сообщением об ошибке if ($POST_RIGHT == "D") { $APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); } // вывод заголовка $APPLICATION->SetTitle("Настройка Pop Up"); // подключаем языковые файлы IncludeModuleLangFile(__FILE__); $aTabs = array( array( // название вкладки в табах "TAB" => "Параметры", // заголовок и всплывающее сообщение вкладки "TITLE" => "Параметры вывода pop-up" ) ); // отрисовываем форму, для этого создаем новый экземпляр класса CAdminTabControl, куда и передаём массив с настройками $tabControl = new CAdminTabControl( "tabControl", $aTabs ); // подключаем модуль для того что бы был видем класс ORM Loader::includeModule("hmarketing.d7"); // Необходимость сохранения изменений мы определим по следующим параметрам: 1)Страница вызвана методом POST; 2)Среди входных данных есть идентификаторы кнопок "Сохранить" и "Применить". Если эти условия сооблюдены и пройдены проверки безопасности, можно сохранять переданные скрипту данные: if ( // проверка метода вызова страницы $REQUEST_METHOD == "POST" && // проверка нажатия кнопок Сохранить $save != "" && // проверка наличия прав на запись для модуля $POST_RIGHT == "W" && // проверка идентификатора сессии check_bitrix_sessid() ) { // класс таблицы в базе данных $bookTable = new \Hmarketing\d7\DataTable; // обработка данных формы $arFields = array( "ACTIVE" => ($ACTIVE == '') ? 'N' : 'Y', "SITE" => json_encode($SITE), "LINK" => htmlspecialchars($LINK), "LINK_PICTURE" => htmlspecialchars($LINK_PICTURE), "ALT_PICTURE" => htmlspecialchars($ALT_PICTURE), "EXCEPTIONS" => $EXCEPTIONS == "" ? "" : trim(htmlspecialchars($EXCEPTIONS)), "DATE" => new \Bitrix\Main\Type\DateTime(date("d.m.Y H:i:s")), "TARGET" => htmlspecialchars($TARGET), ); // обновляем запись $res = $bookTable->Update(1, $arFields); // если обновление прошло успешно if ($res->isSuccess()) { // перенаправим на новую страницу, в целях защиты от повторной отправки формы нажатием кнопки Обновить в браузере if ($save != "") { // если была нажата кнопка Сохранить, отправляем обратно на форму LocalRedirect("/bitrix/admin/hmarketing.php?mess=ok&lang=" . LANG); } } // если обновление прошло не успешно if (!$res->isSuccess()) { // если в процессе сохранения возникли ошибки - получаем текст ошибки if ($e = $APPLICATION->GetException()) $message = new CAdminMessage("Ошибка сохранения: ", $e); else { $mess = print_r($res->getErrorMessages(), true); $message = new CAdminMessage("Ошибка сохранения: " . $mess); } } } // подготовка данных для формы, полученные из БД данные будем сохранять в переменные с префиксом str_ $result = \Hmarketing\d7\DataTable::GetByID(1); if ($result->getSelectedRowsCount()) { $bookTable = $result->fetch(); $str_ACTIVE = $bookTable["ACTIVE"]; $str_SITE = json_decode($bookTable["SITE"]); $str_LINK = $bookTable["LINK"]; $str_LINK_PICTURE = $bookTable["LINK_PICTURE"]; $str_ALT_PICTURE = $bookTable["ALT_PICTURE"]; $str_EXCEPTIONS = $bookTable["EXCEPTIONS"]; $str_TARGET = $bookTable["TARGET"]; } require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php'; // eсли есть сообщения об успешном сохранении, выведем их if ($_REQUEST["mess"] == "ok") { CAdminMessage::ShowMessage(array("MESSAGE" => "Сохранено успешно", "TYPE" => "OK")); } // eсли есть сообщения об не успешном сохранении, выведем их if ($message) { echo $message->Show(); } // eсли есть сообщения об не успешном сохранении от ORM, выведем их if ($bookTable->LAST_ERROR != "") { CAdminMessage::ShowMessage($bookTable->LAST_ERROR); } ?> <form method="POST" action="<?= $APPLICATION->GetCurPage() ?>" ENCTYPE="multipart/form-data" name="post_form"> <? // проверка идентификатора сессии echo bitrix_sessid_post(); // отобразим заголовки закладок $tabControl->Begin(); $tabControl->BeginNextTab(); ?> <tr> <td width="40%"><?= "Активность" ?></td> <td width="60%"><input type="checkbox" name="ACTIVE" value="Y" <? if ($str_ACTIVE == "Y") echo " checked" ?>></td> </tr> <tr> <td> <label for="SITE"><?= "Сайты" ?></label> </td> <td> <select name="SITE[]" multiple> <option value="s1" <?= in_array('s1', $str_SITE) ? 'selected' : '' ?>>Для России</option> <option value="kz" <?= in_array('kz', $str_SITE) ? 'selected' : '' ?>>Для Казахстана</option> </select> </td> </tr> <tr> <td width="40%"><?= "Ссылка для перехода" ?></td> <td width="60%"><input type="text" name="LINK" value="<?= $str_LINK ?>" /></td> </tr> <tr> <td width="40%"><?= "Ссылка на картинку" ?></td> <td width="60%"><input type="text" name="LINK_PICTURE" value="<?= $str_LINK_PICTURE ?>" /></td> </tr> <tr> <td width="40%"><?= "Alt картинки" ?></td> <td width="60%"><input type="text" name="ALT_PICTURE" value="<?= $str_ALT_PICTURE ?>" /></td> </tr> <tr> <td width="40%"><?= "Исключения" ?></td> <td width="60%"><textarea cols="50" rows="15" name="EXCEPTIONS"><?= $str_EXCEPTIONS ?></textarea></td> </tr> <tr> <td width="40%"><?= "Значение TARGET (self/blank)" ?></td> <td width="60%"><input type="text" name="TARGET" value="<?= $str_TARGET ?>" /></td> </tr> <? // выводит стандартные кнопки отправки формы $tabControl->Buttons(); ?> <input class="adm-btn-save" type="submit" name="save" value="Сохранить настройки" /> <? // завершаем интерфейс закладки $tabControl->End(); require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php'; ?>
Файл /install/admin/hmarketing.php
Файл будет скопирован в дирикторию bitrix и будет инклудить админку для пользователей Битрикс.
local/modules/hmarketing.d7/install/admin/hmarketing.php
<? // определяем в какой папке находится модуль, если в bitrix, инклудим файл с меню из папки bitrix if (is_dir($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/hmarketing.d7/")) { // присоединяем и копируем файл require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/hmarketing.d7/admin/hmarketing.php"); } // определяем в какой папке находится модуль, если в local, инклудим файл с меню из папки local if (is_dir($_SERVER["DOCUMENT_ROOT"] . "/local/modules/hmarketing.d7/")) { // присоединяем и копируем файл require_once($_SERVER["DOCUMENT_ROOT"] . "/local/modules/hmarketing.d7/admin/hmarketing.php"); }
Файл /install/files/hmarketing.php
Файл будет скопирован в дирикторию
. Имя класса должно соответствовать названию папке модуля и являться наследником от
CModule
. Только вместо точки, если мы делаемпартнерский модуль
стоит прописать нижние подчеркивание, это нужно для определения модуля в системе. Файл выполняется при установке или удалении модуля через административный интерфейс.В конструкторе класса указывается справочная информация о модуле, часть информации обязательна, часть нет. Данный класс должен присвоить значения свойствам:
public $MODULE_NAME; public $MODULE_DESCRIPTION; public $MODULE_VERSION; public $MODULE_VERSION_DATE; public $MODULE_ID; public $MODULE_SORT; public $SHOW_SUPER_ADMIN_GROUP_RIGHTS; public $MODULE_GROUP_RIGHTS; public $PARTNER_NAME; public $PARTNER_URI;
Тут все довольно тривиально, за исключением версии модуля. Номер версии модуля должен храниться в файле
/install/version.php
в виде массива. Плюс к этому нужно в классе модуля записывать эти значения.В методах класса должны обязатально присутствовать:
DoInstall
отрабатывает при установке модуля, внутри должна вызываться функцияRegisterModule
для регистрации модуля в базе. Так же доступны дополнительные методы для: создания/удаления таблицы в базе, установки/удаления событий и дополнительных файлов модуля. Для реализации нашего модуля не нужны события и дополнительные файлы, методы оставим пустыми для будущего расширения возможностей модуляDoUninstall
отрабатывает при удалении модуля, внутри должна вызываться функцияUnRegisterModule
для удаления регистрации модуля в базе. Так же доступны дополнительные методы для: создания/удаления таблицы в базе, установки/удаления событий и дополнительных файлов модуля. Для реализации нашего модуля не нужны события и дополнительные файлы, методы оставим пустыми для будущего расширения возможностей модуля
Кроме этого, заложены заранее предустановленный наборы методов, которые должны проинсталлировать файлы модуля, события и данные для БД —
InstallFiles
,InstallEvents
,InstallDB
в автоматическом режиме.local/modules/hmarketing.d7/install/index.php
<? // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // пространство имен для управления (регистрации/удалении) модуля в системе/базе use Bitrix\Main\ModuleManager; // пространство имен для работы с параметрами модулей хранимых в базе данных use Bitrix\Main\Config\Option; // пространство имен с абстрактным классом для любых приложений, любой конкретный класс приложения является наследником этого абстрактного класса use Bitrix\Main\Application; // пространство имен для работы c ORM use \Bitrix\Main\Entity\Base; // пространство имен для автозагрузки модулей use \Bitrix\Main\Loader; // пространство имен для событий use \Bitrix\Main\EventManager; // подключение ланговых файлов Loc::loadMessages(__FILE__); class Hmarketing_D7 extends CModule { // переменные модуля public $MODULE_ID; public $MODULE_VERSION; public $MODULE_VERSION_DATE; public $MODULE_NAME; public $MODULE_DESCRIPTION; public $PARTNER_NAME; public $PARTNER_URI; public $SHOW_SUPER_ADMIN_GROUP_RIGHTS; public $MODULE_GROUP_RIGHTS; public $errors; // конструктор класса, вызывается автоматически при обращение к классу function __construct() { // создаем пустой массив для файла version.php $arModuleVersion = array(); // подключаем файл version.php include_once(__DIR__ . '/version.php'); // версия модуля $this->MODULE_VERSION = $arModuleVersion['VERSION']; // дата релиза версии модуля $this->MODULE_VERSION_DATE = $arModuleVersion['VERSION_DATE']; // id модуля $this->MODULE_ID = "hmarketing.d7"; // название модуля $this->MODULE_NAME = "Пример модуля D7"; // описание модуля $this->MODULE_DESCRIPTION = "Тестовый модуль для разработчиков, можно использовать как основу для разработки новых модулей для Битрикс"; // имя партнера выпустившего модуль $this->PARTNER_NAME = "Эйч Маркетинг"; // ссылка на рисурс партнера выпустившего модуль $this->PARTNER_URI = "https://hmarketing.ru"; // если указано, то на странице прав доступа будут показаны администраторы и группы $this->SHOW_SUPER_ADMIN_GROUP_RIGHTS = 'Y'; // если указано, то на странице редактирования групп будет отображаться этот модуль $this->MODULE_GROUP_RIGHTS = 'Y'; } // метод отрабатывает при установке модуля function DoInstall() { //*************************************// // Пример с установкой в один шаг // //*************************************// // // глобальная переменная с обстрактным классом // global $APPLICATION; // // регистрируем модуль в системе // ModuleManager::RegisterModule("hmarketing.d7"); // // создаем таблицы баз данных, необходимые для работы модуля // $this->InstallDB(); // // создаем первую и единственную запись в БД // $this->addData(); // // регистрируем обработчики событий // $this->InstallEvents(); // // копируем файлы, необходимые для работы модуля // $this->InstallFiles(); // // устанавливаем агента // $this->installAgents(); // // подключаем скрипт с административным прологом и эпилогом // $APPLICATION->includeAdminFile( // Loc::getMessage('INSTALL_TITLE'), // __DIR__ . '/instalInfo.php' // ); //*************************************// // Пример с установкой в два шага // //*************************************// // получаем контекст и из него запросы $context = Application::getInstance()->getContext(); $request = $context->getRequest(); // глобальная переменная с обстрактным классом global $APPLICATION; // проверяем какой сейчас шаг, если он не существует или меньше 2, то выводим первый шаг установки if ($request["step"] < 2) { // подключаем скрипт с административным прологом и эпилогом $APPLICATION->IncludeAdminFile( Loc::getMessage('INSTALL_TITLE_STEP_1'), __DIR__ . '/instalInfo-step1.php' ); } // проверяем какой сейчас шаг, усли 2, производим установку if ($request["step"] == 2) { // регистрируем модуль в системе ModuleManager::RegisterModule("hmarketing.d7"); // создаем таблицы баз данных, необходимые для работы модуля $this->InstallDB(); // регистрируем обработчики событий $this->InstallEvents(); // копируем файлы, необходимые для работы модуля $this->InstallFiles(); // устанавливаем агента $this->installAgents(); // проверяим ответ формы введеный пользователем на первом шаге if ($request["add_data"] == "Y") { // создаем первую и единственную запись в БД $this->addData(); } // подключаем скрипт с административным прологом и эпилогом $APPLICATION->IncludeAdminFile( Loc::getMessage('INSTALL_TITLE_STEP_2'), __DIR__ . '/instalInfo-step2.php' ); } // для успешного завершения, метод должен вернуть true return true; } // метод отрабатывает при удалении модуля function DoUninstall() { //*************************************// // Пример с удалением в один шаг // //*************************************// // // глобальная переменная с обстрактным классом // global $APPLICATION; // // удаляем таблицы баз данных, необходимые для работы модуля // $this->UnInstallDB(); // // удаляем обработчики событий // $this->UnInstallEvents(); // // удаляем файлы, необходимые для работы модуля // $this->UnInstallFiles(); // // удаляем агента // $this->unInstallAgents(); // // удаляем регистрацию модуля в системе // ModuleManager::UnRegisterModule("hmarketing.d7"); // // подключаем скрипт с административным прологом и эпилогом // $APPLICATION->includeAdminFile( // Loc::getMessage('DEINSTALL_TITLE'), // __DIR__ . '/deInstalInfo.php' // ); //*************************************// // Пример с удалением в два шага // //*************************************// // получаем контекст и из него запросы $context = Application::getInstance()->getContext(); $request = $context->getRequest(); // глобальная переменная с обстрактным классом global $APPLICATION; // проверяем какой сейчас шаг, если он не существует или меньше 2, то выводим первый шаг удаления if ($request["step"] < 2) { // подключаем скрипт с административным прологом и эпилогом $APPLICATION->IncludeAdminFile( Loc::getMessage('DEINSTALL_TITLE_1'), __DIR__ . '/deInstalInfo-step1.php' ); } // проверяем какой сейчас шаг, усли 2, производим удаление if ($request["step"] == 2) { // удаляем таблицы баз данных, необходимые для работы модуля //$this->UnInstallDB(); // проверяим ответ формы введеный пользователем на первом шаге if ($request["save_data"] == "Y") { // удаляем таблицы баз данных, необходимые для работы модуля $this->UnInstallDB(); } // удаляем обработчики событий $this->UnInstallEvents(); // удаляем файлы, необходимые для работы модуля $this->UnInstallFiles(); // удаляем агента $this->unInstallAgents(); // удаляем регистрацию модуля в системе ModuleManager::UnRegisterModule("hmarketing.d7"); // подключаем скрипт с административным прологом и эпилогом $APPLICATION->IncludeAdminFile( Loc::getMessage('DEINSTALL_TITLE_2'), __DIR__ . '/deInstalInfo-step2.php' ); } // для успешного завершения, метод должен вернуть true return true; } // метод для создания таблицы баз данных function InstallDB() { // подключаем модуль для того что бы был видем класс ORM Loader::includeModule($this->MODULE_ID); // через класс Application получаем соединение по переданному параметру, параметр берем из ORM-сущности (он указывается, если необходим другой тип подключения, отличный от default), если тип подключения по умолчанию, то параметр можно не передавать. Далее по подключению вызываем метод isTableExists, в который передаем название таблицы полученное с помощью метода getDBTableName() класса Base if (!Application::getConnection(\Hmarketing\d7\DataTable::getConnectionName())->isTableExists(Base::getInstance("\Hmarketing\d7\DataTable")->getDBTableName())) { // eсли таблицы не существует, то создаем её по ORM сущности Base::getInstance("\Hmarketing\d7\DataTable")->createDbTable(); } if (!Application::getConnection(\Hmarketing\d7\DataTable::getConnectionName())->isTableExists(Base::getInstance("\Hmarketing\d7\AuthorTable")->getDBTableName())) { // eсли таблицы не существует, то создаем её по ORM сущности Base::getInstance("\Hmarketing\d7\AuthorTable")->createDbTable(); } } // метод для удаления таблицы баз данных function UnInstallDB() { // подключаем модуль для того что бы был видем класс ORM Loader::includeModule($this->MODULE_ID); // делаем запрос к бд на удаление таблицы, если она существует, по подключению к бд класса Application с параметром подключения ORM сущности Application::getConnection(\Hmarketing\d7\DataTable::getConnectionName())->queryExecute('DROP TABLE IF EXISTS ' . Base::getInstance("\Hmarketing\d7\DataTable")->getDBTableName()); Application::getConnection(\Hmarketing\d7\DataTable::getConnectionName())->queryExecute('DROP TABLE IF EXISTS ' . Base::getInstance("\Hmarketing\d7\AuthorTable")->getDBTableName()); // удаляем параметры модуля из базы данных битрикс Option::delete($this->MODULE_ID); } // метод для создания обработчика событий function InstallEvents() { // для произвольной работы EventManager::getInstance()->registerEventHandler( // идентификатор модуля-источника события $this->MODULE_ID, // событие на которое мы подписываемся, OnSomeEvent для произвольной работы "OnSomeEvent", // идентификатор модуля, который подписывается $this->MODULE_ID, // класс выполняющий обработку (для callback-обработчика, если файловый - пустая строка) "\Hmarketing\d7\Main", // метод класса выполняющий обработку (для callback-обработчика, если файловый - пустая строка) 'get' ); // для работы с ORM, есть три типа событий: onBefore<Action> - перед вызовом запроса (можно изменить входные параметры), после следуют валидаторы. on<Action> - уже нельзя изменить входные параметры, после выполняется SQL-запрос. onAfter<Action> - после выполнения операции, операция уже совершена // три события <Action> итого 9 событий: Add, Update, Delete EventManager::getInstance()->registerEventHandler( // идентификатор модуля, для которого регистрируется событие $this->MODULE_ID, // тип события, класс называется DataTable, но должно передаваться по имени файла, то есть просто Data "\Hmarketing\d7\Data::OnBeforeUpdate", // идентификатор модуля к которому относится регистрируемый обработчик, из какого модуля берется класс, нужно если необходимо связать 2 модуля, если используем один, то дублируем поле с первым $this->MODULE_ID, // класс обработчика "\Hmarketing\d7\Events", // метод обработчика 'eventHandler' ); // для успешного завершения, метод должен вернуть true return true; } // метод для удаления обработчика событий function UnInstallEvents() { // удаление событий, аналогично установке EventManager::getInstance()->unRegisterEventHandler( $this->MODULE_ID, "OnSomeEvent", $this->MODULE_ID, "\Hmarketing\d7\Main", 'get' ); // удаление событий, аналогично установке EventManager::getInstance()->unRegisterEventHandler( $this->MODULE_ID, "\Hmarketing\d7\Data::OnBeforeUpdate", $this->MODULE_ID, "\Hmarketing\d7\Events", 'eventHandler' ); // для успешного завершения, метод должен вернуть true return true; } // метод для копирования файлов модуля при установке function InstallFiles() { // скопируем файлы на страницы админки из папки в битрикс, копирует одноименные файлы из одной директории в другую директорию CopyDirFiles( __DIR__ . "/admin", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/admin", true, // перезаписывает файлы true // копирует рекурсивно ); // скопируем компоненты из папки в битрикс, копирует одноименные файлы из одной директории в другую директорию CopyDirFiles( __DIR__ . "/components", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/components", true, // перезаписывает файлы true // копирует рекурсивно ); // копируем файлы страниц, копирует одноименные файлы из одной директории в другую директорию CopyDirFiles( __DIR__ . '/files', $_SERVER["DOCUMENT_ROOT"] . '/', true, // перезаписывает файлы true // копирует рекурсивно ); // для успешного завершения, метод должен вернуть true return true; } // метод для удаления файлов модуля при удалении function UnInstallFiles() { // удалим файлы из папки в битрикс на страницы админки, удаляет одноименные файлы из одной директории, которые были найдены в другой директории, функция не работает рекурсивно DeleteDirFiles( __DIR__ . "/admin", $_SERVER["DOCUMENT_ROOT"] . "/bitrix/admin" ); // удалим компонент из папки в битрикс if (is_dir($_SERVER["DOCUMENT_ROOT"] . "/bitrix/components/" . $this->MODULE_ID)) { // удаляет папка из указанной директории, функция работает рекурсивно DeleteDirFilesEx( "/bitrix/components/" . $this->MODULE_ID ); } // удалим файлы страниц, удаляет одноименные файлы из одной директории, которые были найдены в другой директории, функция не работает рекурсивно DeleteDirFiles( __DIR__ . "/files", $_SERVER["DOCUMENT_ROOT"] . "/" ); // для успешного завершения, метод должен вернуть true return true; } // заполнение таблиц тестовыми данными function addData() { // подключаем модуль для видимости ORM класса Loader::includeModule($this->MODULE_ID); // добавляем запись в таблицу БД \Hmarketing\d7\DataTable::add( array( "ACTIVE" => "N", "SITE" => '["s1"]', "LINK" => " ", "LINK_PICTURE" => "/bitrix/components/hmarketing.d7/popup.baner/templates/.default/img/banner.jpg", "ALT_PICTURE" => " ", "EXCEPTIONS" => " ", "DATE" => new \Bitrix\Main\Type\DateTime(date("d.m.Y H:i:s")), "TARGET" => "self", "AUTHOR_ID" => "1", ) ); // добавляем запись в таблицу БД \Hmarketing\d7\AuthorTable::add( array( "NAME" => "Иван", "LAST_NAME" => "Иванов", ) ); // для успешного завершения, метод должен вернуть true return true; } // установка агентов function installAgents() { \CAgent::AddAgent( // строка PHP для запуска агента-функции "\Hmarketing\d7\Agent::superAgent();", // идентификатор модуля, необходим для подключения файлов модуля (необязательный) $this->MODULE_ID, // период, нужен для агентов, которые должны выполняться точно в срок. Если агент пропустил запуск, то он сделает его столько раз, сколько он пропустил. Если значение N, то агент после первого запуска будет запускаться с заданным интервалам (необязательный, по умолчанию N) "N", // интервал в секундах (необязательный, по умолчанию 86400 (сутки)) 120, // дата первой проверки (необязательный, по умолчанию текущее время) "", // активность агента (необязательный, по умолчанию Y) "Y", // дата первого запуска (необязательный, по умолчанию текущее время) "", // сортировка (влияет на порядок выполнения агентов (очередность), для тех, которые запускаются в одно время) (необязательный, по умолчанию 100) 100 ); } // удаление агентов function unInstallAgents() { \CAgent::RemoveModuleAgents($this->MODULE_ID); } }
Файл /install/instalInfo-step1.php
Файл вызывается при установки модуля из
/install/index.php
Установка модуля в несколько шагов (1-й шаг).
local/modules/hmarketing.d7/install/instalInfo-step1.php
<? // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } ?> <!-- выводим кнопку для перехода на страницу модулей, мы и так находимся на этой странице но с выведенным файлом, значит просто получаем текущую директорию для перенаправления --> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- обязательное получение сессии --> <?= bitrix_sessid_post() ?> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- айди модуля для установки --> <input type="hidden" name="id" value="hmarketing.d7"> <!-- обязательно указывать поле install со значением Y, иначе просто перейдем на страницу модулей --> <input type="hidden" name="install" value="Y"> <!-- определение шага установки модуля --> <input type="hidden" name="step" value="2"> <!-- чекбокс для определния параметра --> <p><?= Loc::getMessage("MOD_ADD_DATA") ?></p> <p><input type="checkbox" name="add_data" id="add_data" value="Y" checked><label for="add_data"><?= Loc::getMessage("MOD_ADD_DATA_BUTTON") ?></label></p> <!-- MOD_INSTALL - системная языковая переменная для кнопки установки --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_INSTALL") ?>"> </form>
Файл /install/instalInfo-step2.php
Файл вызывается при установки модуля из
/install/index.php
Установка модуля в несколько шагов (2-й шаг).
local/modules/hmarketing.d7/install/instalInfo-step2.php
<? // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } // проверяем была ли выброшена ошибка при установке, если да, то записываем её в переменную $errorException if ($errorException = $APPLICATION->getException()) { // вывод сообщения об ошибке при установке модуля CAdminMessage::showMessage( Loc::getMessage('INSTALL_FAILED') . ': ' . $errorException->GetString() ); } else { // вывод уведомления при успешной установке модуля CAdminMessage::showNote( Loc::getMessage('INSTALL_SUCCESS') ); } ?> <!-- выводим кнопку для перехода на страницу модулей, мы и так находимся на этой странице но с выведенным файлом, значит просто получаем текущую директорию для перенаправления --> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- MOD_BACK - системная языковая переменная для возврата --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_BACK") ?>"> </form>
Файл /install/instalInfo.php
Файл вызывается при установки модуля из
/install/index.php
Установка модуля в один шаг.
local/modules/hmarketing.d7/install/instalInfo.php
<? // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } // проверяем была ли выброшена ошибка при установке, если да, то записываем её в переменную $errorException if ($errorException = $APPLICATION->getException()) { // вывод сообщения об ошибке при установке модуля CAdminMessage::showMessage( Loc::getMessage('INSTALL_FAILED') . ': ' . $errorException->GetString() ); } else { // вывод уведомления при успешной установке модуля CAdminMessage::showNote( Loc::getMessage('INSTALL_SUCCESS') ); } ?> <!-- выводим кнопку для перехода на страницу модулей, мы и так находимся на этой странице но с выведенным файлом, значит просто получаем текущую директорию для перенаправления --> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- MOD_BACK - системная языковая переменная для возврата --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_BACK") ?>"> </form>
Файл /install/deInstalInfo-step1.php
Файл вызывается при установки модуля из
/install/index.php
Удаление модуля в несколько шагов (1-й шаг).
local/modules/hmarketing.d7/install/deInstalInfo-step1.php
<? // пространство имен для подключений ланговых файлов use \Bitrix\Main\Localization\Loc; // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } ?> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- обязательное получение сессии --> <?= bitrix_sessid_post() ?> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- айди модуля для удаления --> <input type="hidden" name="id" value="hmarketing.d7"> <!-- обязательно указывать поле uninstall со значением Y, иначе просто перейдем на страницу модулей --> <input type="hidden" name="uninstall" value="Y"> <!-- определение шага удаления модуля --> <input type="hidden" name="step" value="2"> <!-- предупреждение об удалении модуля, MOD_UNINST_WARN - системная языковая переменная --> <?= CAdminMessage::ShowMessage(Loc::getMessage("MOD_UNINST_WARN")) ?> <!-- чекбокс для определния параметра удаления, MOD_UNINST_SAVE - системная языковая переменная --> <p><?= Loc::getMessage("MOD_UNINST_SAVE") ?></p> <!-- MOD_UNINST_DATA - системная языковая переменная --> <p><input type="checkbox" name="save_data" id="save_data" value="Y" checked><label for="save_data"><?= Loc::getMessage("MOD_UNINST_DATA") ?></label></p> <!-- MOD_UNINST_DATA_BUTTON - системная языковая переменная --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_UNINST_DATA_BUTTON") ?>"> </form>
Файл /install/deInstalInfo-step2.php
Файл вызывается при установки модуля из
/install/index.php
Удаление модуля в несколько шагов (2-й шаг).
local/modules/hmarketing.d7/install/deInstalInfo-step2.php
<? // пространство имен для подключений ланговых файлов use \Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } // метод возвращает объект класса CApplicationException, содержащий последнее исключение if ($errorException = $APPLICATION->getException()) { // вывод сообщения об ошибке при удалении модуля CAdminMessage::showMessage( Loc::getMessage('DEINSTALL_FAILED') . ': ' . $errorException->GetString() ); } else { // вывод уведомления при успешном удалении модуля CAdminMessage::showNote( Loc::getMessage('DEINSTALL_SUCCESS') ); } ?> <!-- выводим кнопку для перехода на страницу модулей, мы и так находимся на этой странице но с выведенным файлом, значит просто получаем текущую директорию для перенаправления --> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- MOD_BACK - системная языковая переменная для возврата --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_BACK") ?>"> </form>
Файл /install/deInstalInfo.php
Файл вызывается при установки модуля из
/install/index.php
Удаление модуля в один шаг.
local/modules/hmarketing.d7/install/deInstalInfo.php
<? // пространство имен для подключений ланговых файлов use \Bitrix\Main\Localization\Loc; // подключение ланговых файлов Loc::loadMessages(__FILE__); // проверка идентификатора сессии if (!check_bitrix_sessid()) { return; } // метод возвращает объект класса CApplicationException, содержащий последнее исключение if ($errorException = $APPLICATION->getException()) { // вывод сообщения об ошибке при удалении модуля CAdminMessage::showMessage( Loc::getMessage('DEINSTALL_FAILED') . ': ' . $errorException->GetString() ); } else { // вывод уведомления при успешном удалении модуля CAdminMessage::showNote( Loc::getMessage('DEINSTALL_SUCCESS') ); } ?> <!-- выводим кнопку для перехода на страницу модулей, мы и так находимся на этой странице но с выведенным файлом, значит просто получаем текущую директорию для перенаправления --> <form action="<?= $APPLICATION->GetCurPage() ?>"> <!-- в форме обязательно должно быть поле lang, с айди языка, чтобы язык не сбросился --> <input type="hidden" name="lang" value="<?= LANGUAGE_ID ?>"> <!-- MOD_BACK - системная языковая переменная для возврата --> <input type="submit" name="" value="<?= Loc::getMessage("MOD_BACK") ?>"> </form>
Файл /install/version.php
Файл вызывается при установки модуля из
/install/index.php
Номер версии модуля должен храниться в файле
/install/version.php
в виде массива. Плюс к этому нужно в классе модуля записывать эти значения. В связи с этим нужно налепить небольшую городушку, которая будет брать значение из этого файла и записывать его в модуль:local/modules/hmarketing.d7/install/version.php
<? $arModuleVersion = array( 'VERSION' => '1.0.0', 'VERSION_DATE' => '2023-01-01 10:00:00' );
Файлы в дириктории /lang/ru/
Файл вызывается ядром Битрикс автоматически при установке модуля.
Файлы служат для реализации переводов, в них находится простой массив
$MESS
в котором хранятся парыключ=>значение
перевода, частьru
в пути к файлу является указанимем на язык перевода:/lang/ru/install/deInstalInfo-step1.php
<? $MESS["MOD_UNINST_DATA"] = "Удалить данные таблицы?"; $MESS["MOD_UNINST_DATA_BUTTON"] = "Выполнить";
/lang/ru/install/deInstalInfo-step2.php
<? $MESS['DEINSTALL_FAILED'] = 'Ошибка при удалении модуля'; $MESS['DEINSTALL_SUCCESS'] = 'Модуль успешно удален';
/lang/ru/install/deInstalInfo.php
<? $MESS['DEINSTALL_FAILED'] = 'Ошибка при удалении модуля'; $MESS['DEINSTALL_SUCCESS'] = 'Модуль успешно удален';
/lang/ru/install/index.php
<? $MESS['INSTALL_TITLE'] = 'Установка модуля'; $MESS['INSTALL_TITLE_STEP_1'] = 'Установка модуля шаг 1'; $MESS['INSTALL_TITLE_STEP_2'] = 'Установка модуля шаг 2'; $MESS['DEINSTALL_TITLE'] = 'Удаление модуля'; $MESS['DEINSTALL_TITLE_STEP_1'] = 'Удаление модуля шаг 1'; $MESS['DEINSTALL_TITLE_STEP_2'] = 'Удаление модуля шаг 2';
/lang/ru/install/instalInfo-step1.php
<? $MESS["MOD_ADD_DATA"] = "Записать тестовые данные?"; $MESS["MOD_ADD_DATA_BUTTON"] = "Выполнить";
/lang/ru/install/instalInfo-step2.php
<? $MESS['INSTALL_SUCCESS'] = 'Модуль успешно установлен'; $MESS['INSTALL_FAILED'] = 'Ошибка при установке модуля';
/lang/ru/install/instalInfo.php
<? $MESS['INSTALL_SUCCESS'] = 'Модуль успешно установлен'; $MESS['INSTALL_FAILED'] = 'Ошибка при установке модуля'; $MESS['RETURN_MODULES'] = 'Вернуться в список модулей';
/lang/ru/lib/data.php
<? $MESS["DATA_ENTITY_ID_FIELD"] = "ID"; $MESS["DATA_ENTITY_TITLE_FIELD"] = "Заголовок"; $MESS["DATA_ENTITY_SORT_FIELD"] = "Сортировка"; $MESS["DATA_ENTITY_CREATED_FIELD"] = "Дата создания";
Файл /lib/Main.php
Файл вызывается из файла
/include.php
, или за счет правильного расположения с автоподключением через простраство имен.В данном файле пристуствует
namespace
, который называется в соответвии с требованиями Битрикс. В нем будет храниться основная логика работы модуля, для примера реализуем в данном файле получение одной записи из таблицы модуля с помощьюORM
классаDataTable
:local/modules/hmarketing.d7/lib/Main.php
<? // пространство имен модуля namespace Hmarketing\d7; // пространство имен для подключения класса с ORM use \Hmarketing\d7\DataTable; // пространство имен для получения данных сущности таблицы по событиям use \Bitrix\Main\Entity\Event; // основной класс модуля class Main { // метод для получения строки из таблицы базы данных public static function get() { // запрос к базе $result = DataTable::getList( array( 'select' => array('*') ) ); // преобразование запроса от базы $row = $result->fetch(); // распечатываем массив с ответом на экран print "<pre>"; print_r($row); print "</pre>"; // возвращаем ответ от баззы return $row; } }
Файл /lib/Agent.php
Файл вызывается из файла
/include.php
, или за счет правильного расположения с автоподключением через простраство имен.Класс с методом для работы агента.
local/modules/hmarketing.d7/lib/Agent.php
<? // пространство имен модуля namespace Hmarketing\d7; // класс агента class Agent { // для примера функция пишет в папку модуля время static public function superAgent() { if (is_dir($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/hmarketing.d7/")) file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/hmarketing.d7/superAgentLog.txt", date("Y-m-d H:i:s"), FILE_APPEND); elseif (is_dir($_SERVER["DOCUMENT_ROOT"] . "/local/modules/hmarketing.d7/")) file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/local/modules/hmarketing.d7/superAgentLog.txt", date("Y-m-d H:i:s"), FILE_APPEND); // функция обязательно должна возвращать имя по которому вызывается, иначе битрикс её удаляет return "\Hmarketing\d7\Agent::superAgent();"; } }
Файл /lib/Author.php
Файл вызывается из файла
/include.php
, или за счет правильного расположения с автоподключением через простраство имен.Вспомогательная таблица модуля написанная через
ORM
. В файле создаётся классDataTable
, который наследуется от классаEntity\DataManager
, который в свою очередь реализует парадигмуORM
. Для того что бы подключить наш класс кORM
, мы должны указать имя таблицы и задать структуру, для этого есть 2 методаgetTableName
иgetMap
соответственно. У Битрикс есть автогенерация класса для реализацииORM
.local/modules/hmarketing.d7/lib/Author.php
<? // пространство имен модуля namespace Hmarketing\d7; // пространство имен для ORM use \Bitrix\Main\Entity; // вторая таблица, с которой связана первая, хранит информацию об авторе class AuthorTable extends Entity\DataManager { public static function getTableName() { return "pop_up_authors"; } public static function getMap() { return array( new Entity\IntegerField( "ID", array( "primary" => true, "autocomplete" => true, ) ), new Entity\StringField( "NAME", array( "required" => true, ) ), new Entity\StringField("LAST_NAME") ); } }
Файл /lib/Data.php
Файл вызывается из файла
/include.php
, или за счет правильного расположения с автоподключением через простраство имен.Основная таблица модуля написанная через
ORM
. В файле создаётся классDataTable
, который наследуется от классаEntity\DataManager
, который в свою очередь реализует парадигмуORM
. Для того что бы подключить наш класс кORM
, мы должны указать имя таблицы и задать структуру, для этого есть 2 методаgetTableName
иgetMap
соответственно. У Битрикс есть автогенерация класса для реализацииORM
.local/modules/hmarketing.d7/lib/Data.php
<? // пространство имен модуля namespace Hmarketing\d7; // пространство имен для ORM use \Bitrix\Main\Entity; // пространство имен для кеша use \Bitrix\Main\Application; // сущность ORM унаследованная от DataManager class DataTable extends Entity\DataManager { // название таблицы в базе данных, если не указывать данную функцию, то таблица в бд сформируется автоматически из неймспейса public static function getTableName() { return "pop_up_table"; } // подключение к БД, если не указывать, то будет использовано значение по умолчанию подключения из файла .settings.php. Если указать, то можно выбрать подключение, которое может быть описано в .setting.php public static function getConnectionName() { return "default"; } // метод возвращающий структуру ORM-сущности public static function getMap() { /* * Типы полей: * DatetimeField - дата и время * DateField - дата * BooleanField - логическое поле да/нет * IntegerField - числовой формат * FloatField - числовой дробный формат * EnumField - список, можно передавать только заданные значения * TextField - text * StringField - varchar */ return array( // ID new Entity\IntegerField( // имя сущности "ID", array( // первичный ключ "primary" => true, // AUTO INCREMENT "autocomplete" => true, ) ), // активность new Entity\BooleanField( 'ACTIVE', array( "values" => array('N', 'Y') ) ), // cайты new Entity\StringField( // имя сущности "SITE", array( // обязательное поле "required" => true, ) ), // ссылка перехода new Entity\StringField( // имя сущности "LINK", array( // обязательное поле "required" => true, ) ), // ссылка на картинку new Entity\StringField( // имя сущности "LINK_PICTURE", array( // имя колонки в таблице "column_name" => "LINK_PICTURE_CODE", // если необходима валидация поля, то используем массив валидации, можем передать сколько угодно валидаторов, использовать как штатные, так и самописные "validation" => function () { return array( // первым укажем штаный валидатор проверки на уникальность поля new Entity\Validator\Unique, // вторым напишем свою функцию, которая проверит на длину строку. Аргументы функции: value - значение поля, primary - массив с первичным ключом, row - весь массив данных, переданный в ::add или ::update, field - объект валидируемого поля - Entity\StringField('LINK_PICTURE', ...) function ($value, $primary, $row, $field) { if (strlen($value) <= 100) return true; else return "Код LINK_PICTURE должен содержать не более 100 символов"; } ); } ) ), // описание картинки new Entity\StringField( // имя сущности "ALT_PICTURE", array( // обязательное поле "required" => true, ) ), // исключения new Entity\TextField( // имя сущности "EXCEPTIONS" ), // дата и время заполнения new Entity\DatetimeField( // имя сущности "DATE", array( 'required' => true, ) ), // затемнение баннера new Entity\EnumField( // имя сущности "TARGET", array( // значения доступные для записи "values" => array('self', 'blank'), // обязательное поле "required" => true, ) ), // поле для хранения айди автора, информация о которых будет храниться в другой таблице, свяжем данную таблицу с другой new Entity\IntegerField( // имя сущности "AUTHOR_ID" ), // для связи двух таблиц, нужно будет создать поле зависимости, фактически такого поля нет в базе, оно является виртуальным new Entity\ReferenceField( // имя сущности "AUTHOR", // связываемая сущность другой таблицы '\Hmarketing\d7\AuthorTable', // this - текущая сущность, ref - связываемая array("=this.AUTHOR_ID" => "ref.ID") ), ); } // // события можно задавать прямо в ORM-сущности, для примера запретим изменять поле LINK_PICTURE // public static function onBeforeUpdate(Entity\Event $event) // { // $result = new Entity\EventResult; // $data = $event->getParameter("fields"); // if (isset($data["LINK_PICTURE"])) { // $result->addError( // new Entity\FieldError( // $event->getEntity()->getField("LINK_PICTURE"), // "Запрещено менять LINK_PICTURE код у баннера" // ) // ); // } // return $result; // } // очистка тегированного кеша при добавлении public static function onAfterAdd(Entity\Event $event) { DataTable::clearCache(); } // очистка тегированного кеша при изменении public static function onAfterUpdate(Entity\Event $event) { DataTable::clearCache(); } // очистка тегированного кеша при удалении public static function onAfterDelete(Entity\Event $event) { DataTable::clearCache(); } // основной метод очистки кеша по тегу public static function clearCache() { // служба пометки кеша тегами $taggedCache = Application::getInstance()->getTaggedCache(); $taggedCache->clearByTag('popup'); } }
Файл /lib/Events.php
Файл вызывается из файла
/include.php
, или за счет правильного расположения с автоподключением через простраство имен.Файл в котором описан класс события.
local/modules/hmarketing.d7/lib/Events.php
<? // пространство имен модуля namespace Hmarketing\d7; // пространство имен для получения данных сущности таблицы по событиям use \Bitrix\Main\Entity\Event; // класс события class Events { // для примера выводит поля при каком-либо действии (в регистраторе задано перед добавлением) static public function eventHandler(Event $event) { $fields = $event->getParameter("fields"); echo "<pre>"; echo "Обработчик события"; var_dump($fields); echo "</pre>"; } }
файл /include.php
Файл вызывается ядром Битрикс автоматически.
Файл необходим для подключения классов или дополнительных файлов модуля. Если соблюдать соответствие
namespace
и имени модуля, то поддерживается автозагрузка класса. Автозагрузка работает медленнее, чем поключение файла вinclude.php
.Если необходимо протестировать автозагрузку классов, нужно закомментировать строку, которая подключает наш класс и запустить тестовую страницу снова.
local/modules/hmarketing.d7/include.php
<? Bitrix\Main\Loader::registerAutoloadClasses( // имя модуля "hmarketing.d7", array( // ключ - имя класса с простанством имен, значение - путь относительно корня сайта к файлу "hmarketing\\d7\\Main" => "lib/Main.php", // файл инклудится за счет правильных имен, иначе будет ошибка при установке и удаленни модуля //"Hmarketing\\d7\\DataTable" => "lib/data.php", ) );
Пример автозагрузки класса
Рассмотрим пример автозагрузки классов, сам класс лежит в файле
asd.metrika/lib/counters.php
:asd.metrika/lib/counters.php
namespace Asd\Metrika; class CountersTable extends Entity\DataManager { public static function update() { } }
Данный класс в
/lib/
принадлежит модулюasd.metrika
, к нему после подключения указанного модуля можно обращаться так:\Asd\Metrika\CountersTable::update();
файл /options.php
Файл вызывается ядром Битрикс автоматически при установке модуля.
Полезно выносить настройки решения на отдельную страницу в админки, для возможности администратора сайта влиять на работу модуля. В Битрикс довольно легко создавать страницы с параметрами для своих модулей.
В панели Битрикс сама страница с настройками находится по адресу
Настройки -> Настройки модулей -> Имя_модуля
:На этой странице можно настроить дуступы для разных групп пользователей.
local/modules/hmarketing.d7/options.php
<? // пространство имен для подключений ланговых файлов use Bitrix\Main\Localization\Loc; // пространство имен для получения ID модуля use Bitrix\Main\HttpApplication; // пространство имен для загрузки необходимых файлов, классов, модулей use Bitrix\Main\Loader; // пространство имен для работы с параметрами модулей хранимых в базе данных use Bitrix\Main\Config\Option; // подключение ланговых файлов Loc::loadMessages(__FILE__); // получение запроса из контекста для обработки данных $request = HttpApplication::getInstance()->getContext()->getRequest(); // получаем id модуля $module_id = htmlspecialcharsbx($request["mid"] != "" ? $request["mid"] : $request["id"]); // получим права доступа текущего пользователя на модуль $POST_RIGHT = $APPLICATION->GetGroupRight($module_id); // если нет прав - отправим к форме авторизации с сообщением об ошибке if ($POST_RIGHT < "S") { $APPLICATION->AuthForm(Loc::getMessage("ACCESS_DENIED")); } // подключение модуля Loader::includeModule($module_id); // настройки модуля для админки в том числе значения по умолчанию $aTabs = array( array( // значение будет вставленно во все элементы вкладки для идентификации (используется для javascript) "DIV" => "edit1", // название вкладки в табах "TAB" => "Название вкладки в табах", // заголовок и всплывающее сообщение вкладки "TITLE" => "Главное название в админке", // массив с опциями секции "OPTIONS" => array( "Название секции checkbox", array( // имя элемента формы, для хранения в бд "hmarketing_checkbox", // поясняющий текст "Поясняющий текс элемента checkbox", // значение по умолчани, значение checkbox по умолчанию "Да" "Y", // тип элемента формы "checkbox" array("checkbox"), ), "Название секции text", array( // имя элемента формы, для хранения в бд "hmarketing_text", // поясняющий текст "Поясняющий текс элемента text", // значение по умолчани, значение text по умолчанию "50" "Жми!", // тип элемента формы "text", ширина, высота array( "text", 10, 50 ) ), "Название секции selectbox", array( // имя элемента формы, для хранения в бд "hmarketing_selectbox", // поясняющий текст "Поясняющий текс элемента selectbox", // значение по умолчани, значение selectbox по умолчанию "left" "460", // тип элемента формы "select" array("selectbox", array( // доступные значения "460" => "460Х306", "360" => "360Х242", )) ), "Название секции multiselectbox", array( // имя элемента формы, для хранения в бд "hmarketing_multiselectbox", // поясняющий текст "Поясняющий текс элемента multiselectbox", // значение по умолчани, значение selectbox по умолчанию "left" "left, bottom", // тип элемента формы "multi select" array("multiselectbox", array( // доступные значения "left" => "Лево", "right" => "Право", "top" => "Верх", "bottom" => "Низ", )) ) ) ), array( // значение будет вставленно во все элементы вкладки для идентификации (используется для javascript) "DIV" => "edit2", // название вкладки в табах из основного языкового файла битрикс "TAB" => Loc::getMessage("MAIN_TAB_RIGHTS"), // заголовок и всплывающее сообщение вкладки из основного языкового файла битрикс "TITLE" => Loc::getMessage("MAIN_TAB_TITLE_RIGHTS") ) ); // проверяем текущий POST запрос и сохраняем выбранные пользователем настройки if ($request->isPost() && check_bitrix_sessid()) { // цикл по вкладкам foreach ($aTabs as $aTab) { // цикл по заполненым пользователем данным foreach ($aTab["OPTIONS"] as $arOption) { // если это название секции, переходим к следующий итерации цикла if (!is_array($arOption)) { continue; } // проверяем POST запрос, если инициатором выступила кнопка с name="Update" сохраняем введенные настройки в базу данных if ($request["Update"]) { // получаем в переменную $optionValue введенные пользователем данные $optionValue = $request->getPost($arOption[0]); // метод getPost() не работает с input типа checkbox, для работы сделал этот костыль if ($arOption[0] == "hmarketing_checkbox") { if ($optionValue == "") { $optionValue = "N"; } } // устанавливаем выбранные значения параметров и сохраняем в базу данных, хранить можем только текст, значит если приходит массив, то разбиваем его через запятую, если не массив сохраняем как есть Option::set($module_id, $arOption[0], is_array($optionValue) ? implode(",", $optionValue) : $optionValue); } // проверяем POST запрос, если инициатором выступила кнопка с name="default" сохраняем дефолтные настройки в базу данных if ($request["default"]) { // устанавливаем дефолтные значения параметров и сохраняем в базу данных Option::set($module_id, $arOption[0], $arOption[2]); } } } } // отрисовываем форму, для этого создаем новый экземпляр класса CAdminTabControl, куда и передаём массив с настройками $tabControl = new CAdminTabControl( "tabControl", $aTabs ); // отображаем заголовки закладок $tabControl->Begin(); ?> <form action="<? echo ($APPLICATION->GetCurPage()); ?>?mid=<? echo ($module_id); ?>&lang=<? echo (LANG); ?>" method="post"> <? foreach ($aTabs as $aTab) { if ($aTab["OPTIONS"]) { // завершает предыдущую закладку, если она есть, начинает следующую $tabControl->BeginNextTab(); // отрисовываем форму из массива __AdmSettingsDrawList($module_id, $aTab["OPTIONS"]); } } // завершает предыдущую закладку, если она есть, начинает следующую $tabControl->BeginNextTab(); // выводим форму управления правами в настройках текущего модуля require_once $_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/admin/group_rights.php"; // подключаем кнопки отправки формы $tabControl->Buttons(); // выводим скрытый input с идентификатором сессии echo (bitrix_sessid_post()); // выводим стандартные кнопки отправки формы ?> <input class="adm-btn-save" type="submit" name="Update" value="Применить" /> <input type="submit" name="default" value="По умолчанию" /> </form> <? // обозначаем конец отрисовки формы $tabControl->End(); // // пример получения значения из настроек модуля конкретного поля // $op = \Bitrix\Main\Config\Option::get( // // ID модуля, обязательный параметр // "hmarketing.d7", // // имя параметра, обязательный параметр // "hmarketing_multiselectbox", // // возвращается значение по умолчанию, если значение не задано // "", // // ID сайта, если значение параметра различно для разных сайтов // false // ); // // пример получения значения из настроек модуля всех полей // $op = \Bitrix\Main\Config\Option::getForModule("hmarketing.d7"); // остальные команды https://dev.1c-bitrix.ru/api_d7/bitrix/main/config/option/index.php
-
Папка