← Назад в блог

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

Пошаговый практический пример создания простого модуля для 1С-Битрикс: структура /local/modules, класс модуля, установка компонента и проверка через админку.

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

Требования

  • 1С-Битрикс: Управление сайтом (любой актуальный релиз)
  • Базовые знания PHP
  • Доступ к файловой системе проекта

Свой простой модуль для 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

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


Файл version.php

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

<?php
$arModuleVersion = [
    "VERSION" => "1.0.0",
    "VERSION_DATE" => "2026-02-09",
];

По документации Битрикс в 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'];
    }

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

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

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

    public function InstallFiles()
    {
        CopyDirFiles(
            __DIR__ . '/install/components',
            $_SERVER['DOCUMENT_ROOT'] . '/local/components',
            true,
            true
        );

        return true;
    }

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

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

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

    public function UnInstallFiles()
    {
        DeleteDirFilesEx('/local/components/vendor/simple.date');
        return true;
    }

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


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

    public function DoInstall()
    {
        global $APPLICATION;

        $this->InstallFiles();
        ModuleManager::registerModule($this->MODULE_ID);

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

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

  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'
        );
    }
}

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

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

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

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

Компонент: vendor:simple.date

.description.php

<?php
$arComponentDescription = [
    'NAME' => 'Текущая дата',
    'DESCRIPTION' => 'Простой компонент для вывода текущей даты',
    'PATH' => [
        'ID' => 'vendor',
        'NAME' => 'Учебные компоненты',
    ],
];

component.php

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

<?php

if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
    die();
}

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

$this->IncludeComponentTemplate();

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

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>

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

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

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

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

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

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

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

<?php
$APPLICATION->IncludeComponent(
    'vendor:simple.date',
    '',
    []
);

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


Настройки модуля (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'
);

Важно:

  • первый параметр — 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');

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

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

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

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

public $MODULE_GROUP_RIGHTS = 'Y';

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


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

global $APPLICATION;

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

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

КодЗначение
Dдоступ запрещён
Rчтение
Wзапись
Xполный доступ

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


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

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

Структура

/local/modules/vendor.simplemodule/
├── lib/
│   └── Service/
│       └── DateProvider.php
├── include.php

include.php

<?php

use Bitrix\Main\Loader;

Loader::registerAutoLoadClasses(
    'vendor.simplemodule',
    [
        'Vendor\\SimpleModule\\Service\\DateProvider' =>
            'lib/Service/DateProvider.php',
    ]
);

Класс

<?php
namespace Vendor\SimpleModule\Service;

class DateProvider
{
    public static function getCurrentDate(): string
    {
        return date('d.m.Y');
    }
}

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

use Vendor\SimpleModule\Service\DateProvider;

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

Критично:

  • 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)
);

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

/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(),
            ]),
        ];
    }
}

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

use Vendor\SimpleModule\DateTable;

DateTable::add([]);

$items = DateTable::getList([
    'order' => ['ID' => 'DESC'],
    'limit' => 5,
])->fetchAll();

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

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

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

В DoInstall():

use Bitrix\Main\EventManager;

EventManager::getInstance()->registerEventHandler(
    'main',
    'OnPageStart',
    'vendor.simplemodule',
    'Vendor\\SimpleModule\\EventHandler',
    'onPageStart'
);

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

В DoUninstall():

EventManager::getInstance()->unRegisterEventHandler(
    'main',
    'OnPageStart',
    'vendor.simplemodule',
    'Vendor\\SimpleModule\\EventHandler',
    'onPageStart'
);

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

/lib/EventHandler.php

<?php
namespace Vendor\SimpleModule;

class EventHandler
{
    public static function onPageStart()
    {
        // минимальная логика
    }
}

Важно:

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

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


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

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

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

/local/modules/vendor.simplemodule/
└── install/
    ├── db/
    │   ├── install.sql
    │   └── uninstall.sql
    └── ...

Да, пути могут быть разными в реальных модулях, но суть по доке: 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)
);

install/db/uninstall.sql

DROP TABLE IF EXISTS vendor_simple_date;

Выполнение 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;
    }
}

Подключаем в 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');
}

Критично:

  • 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();
}

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

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

✅ Правило:

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

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

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

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

Итог

Ты получил:

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

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

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

0 просмотров

Комментарии

Загрузка комментариев...
Пока нет комментариев. Будьте первым!