ГлавнаяСтатьиПроектыОбо мне
ГлавнаяСтатьиПроектыОбо мне
Артур Стамболцян

Артур Стамболцян

Fullstack-разработчик. Делаю быстрые и качественные веб-приложения.

Категории

Bitrix242Гайды2DevOps1

Теги

Bitrix24CRMFastPanelLinuxMDXPHPSSHVPSМодули
← Назад к статьям

Как добавить свой пункт меню в мобильное приложение Битрикс24

2026-06-24
Bitrix24PHP

Как добавить свой пункт меню в мобильное приложение Битрикс24

В коробочном Битрикс24 можно добавить собственный пункт в структуру мобильного меню через PHP-обработчик события onMobileMenuStructureBuilt.

Это удобно, когда нужно открыть внутреннюю мобильную страницу портала: тикеты, заявки, отчеты, инструкции или отдельный мини-интерфейс для сотрудников.

В статье разберём рабочий подход на примере пункта IQTicket, который открывает страницу /mobile/iqticket/index.php.

Что мы делаем

1
Создаем класс меню

Создаем PHP-класс CCustomMobileMenu, который добавляет свои группы и пункты в массив мобильного меню.

2
Регистрируем автозагрузку

Подключаем класс через Loader::registerAutoLoadClasses в local/php_interface/init.php.

3
Регистрируем обработчик

Вешаем обработчик на событие mobile:onMobileMenuStructureBuilt.

4
Создаем мобильную страницу

Добавляем страницу, которую будет открывать пункт меню.

5
Проверяем работу

Проверяем URL, авторизацию, права доступа, кеш и отображение пункта в мобильном приложении.

Структура файлов

Пример структуры на сервере:

init.php
CCustomMobileMenu.php
index.php

Название файла класса лучше держать таким же, как название класса: CCustomMobileMenu.php. Так проще не запутаться в автозагрузке.

Подключение в init.php

Файл:

/local/php_interface/init.php
<?php
 
use Bitrix\Main\Loader;
 
Loader::registerAutoLoadClasses(null, [
    'CCustomMobileMenu' => '/local/php_interface/classes/CCustomMobileMenu.php',
]);
 
AddEventHandler(
    'mobile',
    'onMobileMenuStructureBuilt',
    ['CCustomMobileMenu', 'onMobileMenuStructureBuilt']
);

Если в init.php уже есть открывающий тег <?php, второй раз его добавлять не нужно. Просто вставьте use Bitrix\Main\Loader;, регистрацию автозагрузки и AddEventHandler.

Универсальный класс для пунктов меню

Не стоит делать отдельный класс под каждый пункт. Удобнее держать один универсальный класс и описывать группы и пункты в массиве конфигурации.

Файл:

/local/php_interface/classes/CCustomMobileMenu.php
<?php
 
class CCustomMobileMenu
{
    private const GROUPS = [
        [
            'id' => 'custom_tools',
            'title' => 'Рабочие инструменты',
            'sort' => 300,
            'hidden' => false,
            'items' => [
                [
                    'id' => 'iqticket_mobile',
                    'title' => 'IQTicket',
                    'url' => '/mobile/iqticket/index.php',
                    'sort' => 10,
                    'hidden' => false,
                    'color' => '#8E52EC',
                    'imageUrl' => '/bitrix/js/mobile/images/settings.png',
                    'cache' => false,
                    'useSearchBar' => false,
                ],
            ],
        ],
        // [
        //     'id' => 'reports',
        //     'title' => 'Отчеты',
        //     'sort' => 360,
        //     'hidden' => false,
        //     'items' => [
        //         [
        //             'id' => 'reports_mobile',
        //             'title' => 'Отчеты',
        //             'url' => '/mobile/reports/index.php',
        //             'sort' => 10,
        //             'hidden' => false,
        //             'color' => '#2FC6F6',
        //             'imageUrl' => '/bitrix/js/mobile/images/plus.png',
        //             'cache' => false,
        //             'useSearchBar' => false,
        //         ],
        //     ],
        // ],
    ];
 
    public static function onMobileMenuStructureBuilt(array $menu): array
    {
        foreach (self::GROUPS as $group)
        {
            if (empty($group['id']) || empty($group['title']) || empty($group['items']))
            {
                continue;
            }
 
            $items = [];
 
            foreach ($group['items'] as $item)
            {
                if (empty($item['id']) || empty($item['title']) || empty($item['url']))
                {
                    continue;
                }
 
                $items[] = [
                    'id' => $item['id'],
                    'code' => $item['id'],
                    'title' => $item['title'],
                    'sort' => (int)($item['sort'] ?? 100),
                    'hidden' => (bool)($item['hidden'] ?? false),
                    'color' => $item['color'] ?? '#2FC6F6',
                    'imageUrl' => $item['imageUrl'] ?? '/bitrix/js/mobile/images/settings.png',
                    'attrs' => [
                        'id' => $item['id'],
                        'url' => $item['url'],
                        'cache' => (bool)($item['cache'] ?? false),
                        'useSearchBar' => (bool)($item['useSearchBar'] ?? false),
                    ],
                ];
            }
 
            if (!$items)
            {
                continue;
            }
 
            $menu[] = [
                'id' => $group['id'],
                'code' => $group['id'],
                'title' => $group['title'],
                'sort' => (int)($group['sort'] ?? 100),
                'hidden' => (bool)($group['hidden'] ?? false),
                'items' => $items,
            ];
        }
 
        return $menu;
    }
}

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

Как добавить пункт

В классе достаточно добавить новый элемент в items нужной группы. Например, так можно добавить пункт для базы знаний:

[
    'id' => 'company_kb',
    'title' => 'База знаний',
    'url' => '/mobile/kb/index.php',
    'sort' => 20,
    'hidden' => false,
    'color' => '#31C48D',
    'imageUrl' => '/bitrix/js/mobile/images/plus.png',
    'cache' => false,
    'useSearchBar' => true,
],

Если нужна отдельная группа, добавьте новый элемент в массив GROUPS:

[
    'id' => 'reports',
    'title' => 'Отчеты',
    'sort' => 360,
    'hidden' => false,
    'items' => [
        [
            'id' => 'reports_mobile',
            'title' => 'Отчеты',
            'url' => '/mobile/reports/index.php',
            'sort' => 10,
            'hidden' => false,
            'color' => '#2FC6F6',
            'imageUrl' => '/bitrix/js/mobile/images/plus.png',
            'cache' => false,
            'useSearchBar' => false,
        ],
    ],
],

После этого пункт появится в выбранной группе.

Минимальная мобильная страница

Теперь создадим страницу, которую будет открывать пункт меню.

Файл:

/mobile/iqticket/index.php
<?php
 
require($_SERVER['DOCUMENT_ROOT'] . '/mobile/headers.php');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php');
 
global $APPLICATION, $USER;
 
$APPLICATION->SetTitle('IQTicket');
 
if (!$USER || !$USER->IsAuthorized())
{
    LocalRedirect('/auth/');
}
?>
 
<div style="padding: 16px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;">
    <div style="background: #fff; border-radius: 16px; padding: 16px;">
        <h2 style="margin-top: 0;">Test</h2>
        <p style="margin-bottom: 0;">
            Мобильная страница открылась внутри приложения Битрикс24.
        </p>
    </div>
</div>
 
<?php require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/footer.php'); ?>

Для реального мини-приложения лучше разнести CSS и JS по отдельным файлам:

index.php
app.css
app.js

Что означают параметры меню

Основные поля группы и пункта мобильного меню
ПолеНазначение
idУникальный идентификатор группы или пункта. Лучше использовать стабильный slug.
codeУникальный код элемента. В примере он равен id, но у разных пунктов он не должен повторяться.
titleНазвание, которое увидит пользователь.
sortПорядок группы или пункта. Чем меньше число, тем выше элемент.
hiddenЕсли true, группа или пункт будут скрыты.
colorЦвет плитки или иконки пункта в мобильном меню.
imageUrlПуть к изображению иконки. Например, /bitrix/js/mobile/images/settings.png.
attrs.urlURL страницы, которую нужно открыть.
attrs.cacheЛучше ставить false для динамических страниц.
attrs.useSearchBarПоказывать ли поисковую строку в мобильном контейнере.

Частые ошибки

Указали страницу не в /mobile

Для пункта мобильного меню лучше использовать страницу из раздела /mobile/....

Например, если указать путь на обычную CRM-страницу:

'url' => '/crm/iqticket/index.php'

пункт может не появиться или не открыться корректно внутри мобильного приложения.

Правильный вариант — сделать отдельную мобильную точку входа:

'url' => '/mobile/iqticket/index.php'

А если основная логика уже лежит в другом разделе, например /crm/iqticket/, то в /mobile/iqticket/index.php можно подключить легкий мобильный слой или проксировать нужную логику.

<?php
 
require($_SERVER['DOCUMENT_ROOT'] . '/mobile/headers.php');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/header.php');
 
// здесь можно подключить нужные классы, компоненты или API основного раздела
// но точка входа для мобильного приложения остается в /mobile/iqticket/
 
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/footer.php');

В публичном облачном Битрикс24 этот подход не сработает. Он рассчитан на коробочный Битрикс24 или окружение, где есть доступ к PHP-файлам портала.

Для облачного Bitrix24 без доступа к файловой системе нужно использовать возможности REST-приложений и встраивания, а не local/php_interface/init.php.

Скачать примеры из статьи
CCustomMobileMenu.php, init.php и пример мобильной страницы
24 KB