Модуль уже установлен, а Option::get('mycompany.integration', 'API_KEY') отдаёт пустую строку, хотя ключ в коде прописан. Страница в админке пустая или после сохранения всё сбрасывается. Чаще всего виноваты не "сломанный" Битрикс, а три связанных файла: default_option.php, options.php и вызовы Option API в lib/. Ниже - пошаговая настройка страницы параметров своего модуля на CMS 1С-Битрикс (это не Bitrix24). После чек-листа админ увидит форму, а код прочитает значения без хардкода.
Настройки модуля хранятся в таблице b_option, а значения по умолчанию - в default_option.php. Имя массива дефолтов: точку в ID модуля замените на подчёркивание. В options.php сохраняйте через Option::set только после check_bitrix_sessid(). Option::get без третьего аргумента подтянет дефолт из файла; пустая строка в третьем параметре перебьёт файл.
Запрос "настройка модулей битрикс" в поиске часто ведёт в справку про штатные модули. Наша задача другая: каркас уже есть в своём модуле, а API-ключи и флаги должны жить в админке. Option API - современная замена COption; для нового кода берите Bitrix\Main\Config\Option.
Определите, когда нужна страница настроек модуля
Делайте options.php, если параметры меняет администратор без деплоя: ключи внешних API, URL webhook, режим "тест/боевой". Не делайте страницу для констант, которые задаются один раз при разработке. Хардкод и init.php годятся для прототипа; для модуля после DoInstall нужны Option API и форма.
Схема настроек модуля:
default_option.php (дефолты при установке) → options.php (форма в админке) → Option::get в lib/ и компоненте → b_option в БД
Между dev, staging и production не копируйте b_option вручную - применяйте Sprint Migration. Так же переносят инфоблоки и HL-блоки без расхождений ключей.
Создайте default_option.php с корректным именем массива
Файл лежит в корне модуля: /local/modules/mycompany.integration/default_option.php. Битрикс при установке читает массив и подставляет значения, пока админ ничего не сохранял. До первого Option::set в b_option записей может не быть - это ожидаемо, get вернёт дефолт из PHP-файла.
Типичная ошибка: $mycompany.integration_default_option — точка в имени переменной ломает PHP. Замените точку в ID на подчёркивание: $mycompany_integration_default_option. На практике после переименования дефолты читаются, но если в options.php забыли bitrix_sessid_post(), форма «сохраняется», а Option::set молча не пишет в b_option.
<?php
$mycompany_integration_default_option = [
'API_KEY' => '',
'API_URL' => 'https://api.example.com/v1/',
'DEBUG_MODE' => 'N',
];
Ключи в ВЕРХНЕМ_РЕГИСТРЕ и с теми же именами в options.php и Option::get.
- Шаг 1: Создайте default_option.php рядом с install/index.php.
- Шаг 2: Замените точки в ID модуля на подчёркивание в имени массива.
- Шаг 3: Задайте 3-5 ключей с безопасными дефолтами (пустой API_KEY, N для чекбоксов).
- Шаг 4: Переустановите модуль или вызовите Option::getDefaults('mycompany.integration') для проверки.
- Шаг 5: Убедитесь, что Option::get('mycompany.integration', 'API_URL') без третьего аргумента возвращает URL из файла.
- Шаг 6: Проверьте, что в options.php есть bitrix_sessid_post() и check_bitrix_sessid() перед Option::set.
Нюанс Option::get: явный третий аргумент, даже '', перебивает default_option.php. Не передавайте его без необходимости.
Настройте options.php: вкладки, форма и сохранение
options.php подключается на странице Настройки продукта → Настройки модулей. Партнёрские модули ищите в Маркетплейс → Установленные решения. Каркас: CAdminTabControl, check_bitrix_sessid(), Option::set, bitrix_sessid_post().
<?php
use Bitrix\Main\Config\Option;
use Bitrix\Main\Localization\Loc;
$moduleId = 'mycompany.integration';
Loc::loadMessages(__FILE__);
if ($_SERVER['REQUEST_METHOD'] === 'POST' && check_bitrix_sessid()) {
Option::set($moduleId, 'API_KEY', $_POST['API_KEY'] ?? '');
Option::set($moduleId, 'DEBUG_MODE', $_POST['DEBUG_MODE'] === 'Y' ? 'Y' : 'N');
LocalRedirect($APPLICATION->GetCurPage() . '?mid=' . urlencode($moduleId) . '&lang=' . LANGUAGE_ID);
}
$aTabs = [[
'DIV' => 'edit1',
'TAB' => Loc::getMessage('MYCOMPANY_INTEGRATION_TAB_MAIN'),
'TITLE' => Loc::getMessage('MYCOMPANY_INTEGRATION_TAB_MAIN_TITLE'),
]];
$tabControl = new CAdminTabControl('tabControl', $aTabs);
$tabControl->Begin();
?>
<form method="post">
<?= bitrix_sessid_post() ?>
<?php $tabControl->BeginNextTab(); ?>
<tr>
<td width="40%">API Key:</td>
<td><input type="text" size="50" name="API_KEY"
value="<?= htmlspecialcharsbx(Option::get($moduleId, 'API_KEY')) ?>"></td>
</tr>
<?php $tabControl->Buttons(); ?>
<input type="submit" name="save" value="Сохранить">
</form>
<?php $tabControl->End(); ?>
Без check_bitrix_sessid() форма откроется, но b_option не обновится. Подписи - через Loc::getMessage в lang/ru/options.php. Вторую вкладку добавьте в $aTabs.
Читайте настройки в lib/ и компоненте через Option::get
После того как форма работает, подключите модуль в сервисах lib/ или в компоненте. Один вызов Option::get на ключ - без дублирования дефолтов в parameters.php.
use Bitrix\Main\Config\Option;
use Bitrix\Main\Loader;
Loader::includeModule('mycompany.integration');
$apiKey = Option::get('mycompany.integration', 'API_KEY');
$timeout = (int) Option::get('mycompany.integration', 'TIMEOUT');
В новом модуле не смешивайте COption и Option. Конфигурация - Option; бизнес-данные - в ORM-таблице. Дополнительно: getDefaults (сброс к файлу), getRealValue (только БД), getForModule (все ключи), delete для одного параметра.
Сравните Option API и legacy COption
| Критерий | Bitrix\Main\Config\Option (D7) | COption (legacy) |
|---|---|---|
| Что писать в новом модуле | Да, стандарт с версии 12.0.7 | Только при поддержке старого кода |
| Связь с default_option.php | get() без 3-го аргумента читает файл | Через GetOptionString с дефолтом вручную |
| Namespace и автозагрузка | use Bitrix\Main\Config\Option | Глобальный класс, без namespace |
| Дополнительные методы | getDefaults, getRealValue, getForModule | Нет единого аналога getForModule |
Итоговый вердикт: в options.php и lib/ нового модуля используйте только Option. COption оставьте для чтения чужих legacy-модулей, но не копируйте этот стиль в свой код.
Проверьте результат: чек-лист перед выкладкой на staging
- Модуль установлен, виден в Управление модулями или Установленных решениях.
- default_option.php: подчёркивание вместо точки, ключи = options.php.
- Форма открывается в Настройки модулей.
- После сохранения с sessid значения переживают F5.
- b_option содержит MODULE_ID вашего модуля.
- Option::get в lib/ совпадает с админкой.
- На staging опции через Sprint Migration, не SQL.
Пустой get сразу после установки при корректном default_option.php - норма до первого сохранения; иначе проверьте имя массива и третий аргумент.
Нужна помощь с модулем под интеграцию или обмен с 1С - обсудим задачу. Примеры внедрений смотрите в портфолио.
Автор: Максим Мольков, разработчик 1С-Битрикс.
Источники: документация Option API, курс разработчика: параметры модуля, Habr: default_option.php.
Частые вопросы
Зачем нужен default_option.php, если есть options.php?
default_option.php задаёт значения сразу после установки, до первого захода в админку. options.php только показывает форму и сохраняет изменения в b_option. Без дефолт-файла Option::get после DoInstall часто отдаёт пустую строку.
Где должен лежать options.php?
В корне каталога модуля: /local/modules/vendor.module/options.php, на одном уровне с install/ и include.php. Битрикс подхватывает его автоматически при выборе модуля на странице настроек.
Чем Option отличается от COption?
Option - класс D7 с namespace, читает default_option.php и даёт getDefaults/getForModule. COption - legacy с 3.0.7, встречается в старых модулях. В новом коде пишите только Option::get и Option::set.
Почему Option::get возвращает пусто после установки?
Проверьте имя массива в default_option.php (точка → подчёркивание), совпадение имён ключей и не передавайте третий аргумент '' в get. Убедитесь, что модуль установлен и MODULE_ID в коде совпадает с папкой.
Как добавить вторую вкладку в настройках?
Добавьте элемент в массив $aTabs с новым DIV и TAB, вызовите BeginNextTab() перед блоком полей вкладки. Подписи вынесите в lang/ru/options.php через Loc::getMessage.
Как прочитать настройку модуля в компоненте?
В начале component.php или class.php: Loader::includeModule('vendor.module'), затем Option::get('vendor.module', 'KEY'). Не дублируйте дефолты в parameters.php - берите актуальное значение из Option.
Как перенести опции на другой сервер без ручного SQL?
Экспортируйте и примените миграцию опций через Sprint Migration: так же переносят инфоблоки и HL-блоки. Прямое копирование b_option между средами ломает привязку к разным доменам и версиям модулей.