DEV Community

Андрей Викулов (VProger)
Андрей Викулов (VProger)

Posted on • Originally published at viku-lov.ru on

Свой простой модуль для 1С-Битрикс: от /local/modules до рабочего компонента

Свой простой модуль для 1С-Битрикс: от /local/modules до рабочего компонента

Свой простой модуль для 1С-Битрикс: от /local/modules до рабочего компонента

В этой статье разберём минимальный, но боевой пример собственного модуля под 1С‑Битрикс , который:

  • корректно устанавливается и удаляется через админку;
  • ставит один компонент ;
  • не ломает обновления и соответствует официальному подходу.

Без философии. Только практика и структура из учебного курса Битрикса, но нормальным человеческим языком.


Когда нужен модуль, а не код в /local

Коротко и по делу:

Модуль нужен, когда:

  • код переиспользуется на нескольких проектах;
  • требуется установка/удаление через админку;
  • нужны настройки, версии, права доступа ;
  • компонент — часть функционального блока, а не разовая правка.

Если код живёт только в одном проекте и никогда никуда не поедет — /local/php_interface ок.

Во всех остальных случаях — модуль.


Структура простого модуля

Делаем модуль vendor.simplemodule.

Базовая структура


/local/modules/vendor.simplemodule/

├── install/

│ ├── components/

│ │ └── vendor/

│ │ └── simple.date/

│ │ ├── component.php

│ │ ├── .description.php

│ │ └── templates/

│ │ └── .default/

│ │ └── template.php

│ ├── index.php

│ ├── step.php

│ ├── unstep.php

│ └── version.php

├── lang/

├── include.php

└── vendor.simplemodule.php

Enter fullscreen mode Exit fullscreen mode

Обрати внимание: компонент лежит внутри модуля , а не сразу в /local/components.


Файл version.php

Минимальный, но обязательный.


<?php

$arModuleVersion = [

"VERSION" => "1.0.0",

"VERSION\_DATE" => "2026-02-09",

];

Enter fullscreen mode Exit fullscreen mode

По документации Битрикс в version.php используют двойные кавычки — одинарные могут не отрабатывать при установке.


Класс модуля

Сниппеты по статье: InstallDB/UnInstallDB и SQL · События при установке/удалении · Автозагрузка классов модуля · Проверка B_PROLOG_INCLUDED в компоненте

Файл:

/local/modules/vendor.simplemodule/vendor.simplemodule.php

В структуре по документации класс может быть описан в install/index.php; на практике его часто выносят в корневой файл с именем модуля (например, vendor.simplemodule.php), чтобы подключать через include.php.


<?php

use Bitrix\Main\ModuleManager;

class vendor\_simplemodule extends CModule

{

public $MODULE\_ID = 'vendor.simplemodule';

public $MODULE\_VERSION;

public $MODULE\_VERSION\_DATE;

public $MODULE\_NAME = 'Простой учебный модуль';

public $MODULE\_DESCRIPTION = 'Учебный модуль с одним компонентом';

public $MODULE\_GROUP\_RIGHTS = 'N';

public function \_\_construct()

{

include \_\_DIR\_\_ . '/install/version.php';

$this->MODULE\_VERSION = $arModuleVersion['VERSION'];

$this->MODULE\_VERSION\_DATE = $arModuleVersion['VERSION\_DATE'];

}

Enter fullscreen mode Exit fullscreen mode

Что здесь важно

  • $MODULE_ID строго совпадает с именем папки;
  • версия и дата берутся из version.php;
  • никакой логики — только описание.

Установка файлов (InstallFiles)


public function InstallFiles()

{

CopyDirFiles(

\_\_DIR\_\_ . '/install/components',

$\_SERVER['DOCUMENT\_ROOT'] . '/local/components',

true,

true

);

return true;

}

Enter fullscreen mode Exit fullscreen mode

Что происходит:

  • копируем компоненты из модуля;
  • они появляются в /local/components/vendor/...;
  • Bitrix начинает их видеть.

Удаление файлов (UnInstallFiles)


public function UnInstallFiles()

{

DeleteDirFilesEx('/local/components/vendor/simple.date');

return true;

}

Enter fullscreen mode Exit fullscreen mode

Никакой магии — просто аккуратно удаляем то, что поставили.


Установка модуля (DoInstall)


public function DoInstall()

{

global $APPLICATION;

$this->InstallFiles();

ModuleManager::registerModule($this->MODULE\_ID);

$APPLICATION->IncludeAdminFile(

'Установка модуля',

\_\_DIR\_\_ . '/install/step.php'

);

}

Enter fullscreen mode Exit fullscreen mode

Порядок важен

  1. Копируем файлы
  2. Регистрируем модуль
  3. Показываем шаг установки

В учебном курсе Битрикс в DoInstall() вызывают InstallDB() → InstallEvents() → InstallFiles(), причём в том примере InstallDB() только регистрирует модуль (RegisterModule). Мы используем современный API ModuleManager::registerModule() и показываем шаг установки через IncludeAdminFile — оба варианта соответствуют документации.


Удаление модуля (DoUninstall)


public function DoUninstall()

{

global $APPLICATION;

$this->UnInstallFiles();

ModuleManager::unRegisterModule($this->MODULE\_ID);

$APPLICATION->IncludeAdminFile(

'Удаление модуля',

\_\_DIR\_\_ . '/install/unstep.php'

);

}

}

Enter fullscreen mode Exit fullscreen mode

Файлы step.php и unstep.php

Минимальный вариант.


<?php

echo 'Модуль успешно установлен';

php

<?php

echo 'Модуль успешно удалён';

Enter fullscreen mode Exit fullscreen mode

Простейший компонент внутри модуля

Компонент:

vendor:simple.date

.description.php


<?php

$arComponentDescription = [

'NAME' => 'Текущая дата',

'DESCRIPTION' => 'Простой компонент для вывода текущей даты',

'PATH' => [

'ID' => 'vendor',

'NAME' => 'Учебные компоненты',

],

];

Enter fullscreen mode Exit fullscreen mode

component.php

Защита от прямого вызова — проверка B_PROLOG_INCLUDED (сниппет):


<?php

if (!defined('B\_PROLOG\_INCLUDED') || B\_PROLOG\_INCLUDED !== true) {

die();

}

$arResult['DATE'] = date('d.m.Y');

$this->IncludeComponentTemplate();

Enter fullscreen mode Exit fullscreen mode

Шаблон компонента

templates/.default/template.php — в шаблоне та же проверка (сниппет):


<?php

if (!defined('B\_PROLOG\_INCLUDED') || B\_PROLOG\_INCLUDED !== true) {

die();

}

?>

<div class="simple-date">

Текущая дата: <strong><?= htmlspecialcharsbx($arResult['DATE']) ?></strong>

</div>

Enter fullscreen mode Exit fullscreen mode

Установка и проверка

  1. Установка модуля

Админка → Настройки → Модули → Простой учебный модуль → Установить.

Если не появился:

  • проверь имя папки;
  • проверь $MODULE_ID;
  • обнови список модулей.

  1. Проверка компонента

В визуальном редакторе или в коде:


<?php

$APPLICATION->IncludeComponent(

'vendor:simple.date',

'',

[]

);

Enter fullscreen mode Exit fullscreen mode

Если видишь текущую дату — всё работает.


Настройки модуля (options)

В Битриксе настройки модуля — это значения, хранящиеся в таблице b_option.

Работаем только через API , без самодельных таблиц.

Где живут настройки

  • ключи и значения — в b_option
  • интерфейс — через options.php (если нужен UI)
  • доступ — через \Bitrix\Main\Config\Option

Простейшая настройка без интерфейса


use Bitrix\Main\Config\Option;

// запись

Option::set(

'vendor.simplemodule',

'show\_date',

'Y'

);

// чтение

$showDate = Option::get(

'vendor.simplemodule',

'show\_date',

'N'

);

Enter fullscreen mode Exit fullscreen mode

Важно:

  • первый параметр — MODULE_ID;
  • всегда указывай дефолт;
  • никаких COption (устаревшее API).

Использование настройки в компоненте


use Bitrix\Main\Config\Option;

if (Option::get('vendor.simplemodule', 'show\_date', 'Y') !== 'Y') {

return;

}

$arResult['DATE'] = date('d.m.Y');

Enter fullscreen mode Exit fullscreen mode

Права доступа модуля

Права доступа в модуле — стандартный механизм , не самописный.

Включение поддержки прав

В классе модуля:


public $MODULE\_GROUP\_RIGHTS = 'Y';

Enter fullscreen mode Exit fullscreen mode

После этого в админке появится вкладка «Права доступа».


Проверка прав в коде


global $APPLICATION;

if ($APPLICATION->GetGroupRight('vendor.simplemodule') < 'R') {

return;

}

Enter fullscreen mode Exit fullscreen mode

Стандартные уровни

| Код | Значение |

| --- | --------------- |

| D | доступ запрещён |

| R | чтение |

| W | запись |

| X | полный доступ |

Важно: не выдумывай свои уровни — Bitrix этого не любит.


Автозагрузка классов модуля

Современный способ — через Bitrix\Main\Loader и PSR-4. Готовый шаблон: сниппет «Автозагрузка классов модуля».

Структура


/local/modules/vendor.simplemodule/

├── lib/

│ └── Service/

│ └── DateProvider.php

├── include.php

Enter fullscreen mode Exit fullscreen mode

include.php


<?php

use Bitrix\Main\Loader;

Loader::registerAutoLoadClasses(

'vendor.simplemodule',

[

'Vendor\\SimpleModule\\Service\\DateProvider' =>

'lib/Service/DateProvider.php',

]

);

Enter fullscreen mode Exit fullscreen mode

Класс


<?php

namespace Vendor\SimpleModule\Service;

class DateProvider

{

public static function getCurrentDate(): string

{

return date('d.m.Y');

}

}

Enter fullscreen mode Exit fullscreen mode

Использование


use Vendor\SimpleModule\Service\DateProvider;

$arResult['DATE'] = DateProvider::getCurrentDate();

Enter fullscreen mode Exit fullscreen mode

Критично:

  • namespace в формате Vendor\SimpleModule... (например, Vendor\SimpleModule\Service);
  • путь от корня модуля ;
  • никаких require_once.

Модуль с ORM (DataManager)

ORM в Битриксе — это \Bitrix\Main\Entity\DataManager.

Используется только для своих таблиц.


Таблица


CREATE TABLE vendor\_simple\_date (

ID int NOT NULL AUTO\_INCREMENT,

CREATED\_AT datetime NOT NULL,

PRIMARY KEY (ID)

);

Enter fullscreen mode Exit fullscreen mode

Класс таблицы

/local/modules/vendor.simplemodule/lib/DateTable.php


<?php

namespace Vendor\SimpleModule;

use Bitrix\Main\Entity;

use Bitrix\Main\Type\DateTime;

class DateTable extends Entity\DataManager

{

public static function getTableName()

{

return 'vendor\_simple\_date';

}

public static function getMap()

{

return [

new Entity\IntegerField('ID', [

'primary' => true,

'autocomplete' => true,

]),

new Entity\DatetimeField('CREATED\_AT', [

'required' => true,

'default\_value' => new DateTime(),

]),

];

}

}

Enter fullscreen mode Exit fullscreen mode

Использование ORM


use Vendor\SimpleModule\DateTable;

DateTable::add([]);

$items = DateTable::getList([

'order' => ['ID' => 'DESC'],

'limit' => 5,

])->fetchAll();

Enter fullscreen mode Exit fullscreen mode

События модуля

События подключаются только после установки модуля. Регистрация и снятие в DoInstall/DoUninstall: сниппет «События при установке/удалении».

Регистрация обработчика

В DoInstall():


use Bitrix\Main\EventManager;

EventManager::getInstance()->registerEventHandler(

'main',

'OnPageStart',

'vendor.simplemodule',

'Vendor\\SimpleModule\\EventHandler',

'onPageStart'

);

Enter fullscreen mode Exit fullscreen mode

Удаление обработчика

В DoUninstall():


EventManager::getInstance()->unRegisterEventHandler(

'main',

'OnPageStart',

'vendor.simplemodule',

'Vendor\\SimpleModule\\EventHandler',

'onPageStart'

);

Enter fullscreen mode Exit fullscreen mode

Класс обработчика

/lib/EventHandler.php


<?php

namespace Vendor\SimpleModule;

class EventHandler

{

public static function onPageStart()

{

// минимальная логика

}

}

Enter fullscreen mode Exit fullscreen mode

Важно:

  • события регистрируются и удаляются ;
  • не оставляй «висячие» хендлеры;
  • никакой бизнес-логики в событиях.

Ниже — создание и удаление таблиц через install.sql/uninstall.sql (штатный DB API) и типичные ошибки модулей, из-за которых «падают обновления» и админка начинает ненавидеть тебя.


install.sql / uninstall.sql (создание и удаление таблицы)

Где хранить SQL в модуле

Классический (официальный, учебный) подход — держать SQL внутри install/:


/local/modules/vendor.simplemodule/

└── install/

├── db/

│ ├── install.sql

│ └── uninstall.sql

└── ...

Enter fullscreen mode Exit fullscreen mode

Да, пути могут быть разными в реальных модулях, но суть по доке: SQL выполняем через $DB->RunSQLBatch() (метод принимает путь к .sql-файлу; глобальный $DB — экземпляр CDatabase), а файлы лежат в install-части.


install/db/install.sql


CREATE TABLE IF NOT EXISTS vendor\_simple\_date (

ID INT NOT NULL AUTO\_INCREMENT,

CREATED\_AT DATETIME NOT NULL,

PRIMARY KEY (ID)

);

Enter fullscreen mode Exit fullscreen mode

install/db/uninstall.sql


DROP TABLE IF EXISTS vendor\_simple\_date;

Enter fullscreen mode Exit fullscreen mode

Выполнение SQL при установке/удалении (строго штатно)

Добавляем в класс модуля два метода: InstallDB() и UnInstallDB(). Готовый код с проверкой ошибок: сниппет «InstallDB/UnInstallDB и SQL». В учебнике Битрикс метод InstallDB() иногда используется только для регистрации модуля в БД (RegisterModule); здесь мы используем его для создания своих таблиц, а регистрацию делаем отдельно через ModuleManager::registerModule() в DoInstall() — так делают многие штатные и партнёрские модули.


<?php

use Bitrix\Main\Application;

use Bitrix\Main\IO\Path;

class vendor\_simplemodule extends CModule

{

// ...

public function InstallDB()

{

global $DB;

$sqlPath = $\_SERVER['DOCUMENT\_ROOT'] . '/local/modules/' . $this->MODULE\_ID . '/install/db/install.sql';

if (file\_exists($sqlPath)) {

$errors = $DB->RunSQLBatch($sqlPath);

if (is\_array($errors)) {

throw new \Bitrix\Main\SystemException(implode("\n", $errors));

}

}

return true;

}

public function UnInstallDB()

{

global $DB;

$sqlPath = $\_SERVER['DOCUMENT\_ROOT'] . '/local/modules/' . $this->MODULE\_ID . '/install/db/uninstall.sql';

if (file\_exists($sqlPath)) {

$errors = $DB->RunSQLBatch($sqlPath);

if (is\_array($errors)) {

throw new \Bitrix\Main\SystemException(implode("\n", $errors));

}

}

return true;

}

}

Enter fullscreen mode Exit fullscreen mode

Подключаем в DoInstall() и DoUninstall()


public function DoInstall()

{

global $APPLICATION;

$this->InstallDB();

$this->InstallFiles();

\Bitrix\Main\ModuleManager::registerModule($this->MODULE\_ID);

$APPLICATION->IncludeAdminFile('Установка модуля', \_\_DIR\_\_ . '/install/step.php');

}

public function DoUninstall()

{

global $APPLICATION;

$this->UnInstallFiles();

$this->UnInstallDB();

\Bitrix\Main\ModuleManager::unRegisterModule($this->MODULE\_ID);

$APPLICATION->IncludeAdminFile('Удаление модуля', \_\_DIR\_\_ . '/install/unstep.php');

}

Enter fullscreen mode Exit fullscreen mode

Критично:

  • SQL выполняем до register/unregister — так проще отлаживать;
  • RunSQLBatch() возвращает массив ошибок — его нельзя игнорировать;
  • IF EXISTS/IF NOT EXISTS спасают при повторной установке/удалении.

Типичные ошибки модулей, из-за которых «падают обновления»

Это то, что реально валит проекты после апдейтов, миграций и просто «перестало работать в понедельник».

1) Модуль пишет/правит файлы в /bitrix/*

Плохо: модуль кладёт свои файлы в ядро или меняет файлы ядра.

Почему падает: обновление ядра перезатирает всё. Иногда — вместе с проектом.

✅ Правило: всё своё — в /local. Ядро — не трогаем.


2) Нет симметрии между install и uninstall

Плохо: зарегистрировал обработчики событий, но не удалил; создал таблицы, но не удалил; скопировал компоненты, но не удалил.

Симптомы:

  • дубли обработчиков → код выполняется дважды;
  • ошибки при переустановке;
  • «призраки» в системе.

✅ Правило: что поставил — то убрал (файлы/события/опции/таблицы).


3) Бизнес-логика в DoInstall() / __construct()

Плохо: в конструкторе модуля подключаются классы, бьётся ORM, читаются таблицы, вызываются сервисы.

Почему падает: админка просто открывает список модулей → а у тебя там пол-проекта стартует и валится.

✅ Правило:

  • __construct() — только мета (version.php, name/desc).
  • установка — только инфраструктура (файлы, таблицы, события).

4) Неправильный $MODULE_ID и структура папок

Плохо: папка vendor.simplemodule, а $MODULE_ID = 'vendor.simple_module' или класс модуля называется иначе.

Симптомы: модуль “не виден”, “не ставится”, “не удаляется”.

✅ Правило:

  • папка: vendor.simplemodule
  • $MODULE_ID: vendor.simplemodule
  • класс: vendor_simplemodule (точно как ожидает Bitrix)

5) Компонент кладут не туда

Плохо: компонент лежит прямо в /local/modules/.../components и не копируется, или копируется в /bitrix/components.

✅ Правило:

  • исходники компонента: /install/components/vendor/...
  • установка: копирование в /local/components/vendor/...

6) Классы без автозагрузки, всё через require_once

Плохо: в init.php или component.php пачка require_once, часть путей относительная.

Почему падает: при изменении структуры / кеша / окружения ловишь “Failed opening required”.

✅ Правило:

  • регистрируй автозагрузку через Loader::registerAutoLoadClasses()
  • require_once — только для install-скриптов и то по необходимости.

7) События регистрируются «в рантайме», а не через установку

Плохо: AddEventHandler вызывается в init.php модуля или в include.php без контроля установки.

Почему падает: модуль удалили, а обработчики продолжают жить или подключаться.

✅ Правило:

  • регистрировать события через EventManager в DoInstall()
  • удалять в DoUninstall()

8) Нет проверки B_PROLOG_INCLUDED в компонентах/шаблонах

Плохо: шаблон или component.php может выполняться напрямую.

✅ Правило: в каждом файле компонента/шаблона (сниппет):


if (!defined('B\_PROLOG\_INCLUDED') || B\_PROLOG\_INCLUDED !== true) {

die();

}

Enter fullscreen mode Exit fullscreen mode

9) Грязные опции: не удаляются / конфликтуют по ключам

Плохо: Option::set() без namespace и без удаления при uninstall.

✅ Правило:

  • ключи только под своим MODULE_ID
  • при удалении — чистим опции модуля (если политика проекта это допускает).

Итоговый чек-лист перед продом

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

  • [] Имя папки = $MODULE_ID
  • [] Компоненты копируются в /local/components
  • [] InstallFiles и UnInstallFiles симметричны
  • [] Нет бизнес-логики в классе модуля
  • [] Компонент работает без модуля (после копирования)
  • [] Модуль корректно удаляется и ставится повторно
  • [] Код не трогает /bitrix

Итог

Ты получил:

  • минимальный, но корректный модуль;
  • понятную структуру;
  • компонент, который реально устанавливается;
  • основу для масштабирования (настройки, события, ORM — дальше).

Это ровно тот уровень , с которого стоит начинать писать свои модули под Битрикс — без оверинженеринга и шаманства.

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

Read more on viku-lov.ru

Top comments (0)