Разработка модуля многоуровневого меню 1С-Битрикс

Проблемы стандартных меню и наше решение Стандартный компонент `bitrix:menu` генерирует меню из файлов `.menu.php` или структуры сайта. Для простых сайтов этого достаточно, но когда в каталоге тысячи товаров и нужно управлять мегаменю с картинками, баннерами, колонками — начинаются тормоза. Мы ра
Услуги, которые мы предлагаем
Показано 1 из 1Все 1626 услуг
Разработка модуля многоуровневого меню 1С-Битрикс
Средний
~1-2 недели

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1415
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    995
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    734
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    863
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    772
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    1134

Проблемы стандартных меню и наше решение

Стандартный компонент bitrix:menu генерирует меню из файлов .menu.php или структуры сайта. Для простых сайтов этого достаточно, но когда в каталоге тысячи товаров и нужно управлять мегаменю с картинками, баннерами, колонками — начинаются тормоза. Мы разработали модуль, который решает эти проблемы: даёт гибкое управление через интерфейс с кэшированием и полной поддержкой мегаменю. Модуль подходит для проектов с любым объёмом пунктов — проверено на каталогах до 10 000 позиций.

Почему стандартный bitrix:menu не справляется с большими каталогами?

Одна из главных проблем — отсутствие тегированного кэширования. Каждый запрос перестраивает дерево из файлов, а при динамическом добавлении пунктов через административный интерфейс — невозможно. Наш модуль хранит всё в базе данных и кэширует дерево с тегом, инвалидация происходит при любом изменении. Это даёт выигрыш в скорости в 10–50 раз по сравнению с разбором файлов.

Как мы реализовали масштабируемую модель данных?

Мы использовали ORM Битрикс (таблицы b_vendor_menu_*) с adjacency list для хранения иерархии. Почему adjacency list, а не nested sets? Для меню с частыми изменениями структуры (добавление, удаление, перемещение) adjacency list быстрее на запись, а чтение с кэшем нивелирует разницу.

Модель данных

Модуль vendor.megamenu:

  • b_vendor_menu_config — конфигурации меню: id, code, name, site_id, lang, is_active
  • b_vendor_menu_item — пункты меню: id, menu_id, parent_id, sort, title, url, url_type (absolute/relative/component), target, icon_id, image_id, css_class, visibility (all/authorized/unauthorized), condition (JSON), is_active
  • b_vendor_menu_column — колонки мегаменю для пункта второго уровня: id, item_id, title, sort, items (JSON — ссылки без отдельных записей)
  • b_vendor_menu_banner — баннеры в мегаменю: id, item_id, image_id, url, title, sort

Дерево пунктов меню

Пункты хранятся в adjacency list (parent_id). Для построения дерева используется итеративный обход, чтобы избежать рекурсии в PHP:

class MenuTreeBuilder { public function build(int $menuId): array { $items = MenuItemTable::getList([ 'filter' => ['MENU_ID' => $menuId, 'IS_ACTIVE' => 'Y'], 'order' => ['PARENT_ID' => 'ASC', 'SORT' => 'ASC'], ])->fetchAll(); $tree = []; $index = []; foreach ($items as $item) { $item['children'] = []; $index[$item['ID']] = &$item; } foreach ($index as &$item) { if ($item['PARENT_ID']) { $index[$item['PARENT_ID']]['children'][] = &$item; } else { $tree[] = &$item; } } return $tree; } } 

Дерево кешируется целиком тегом menu_{code}_{lang}. Инвалидация — при любом изменении пункта или баннера этого меню.

Видимость пунктов

Условия видимости пункта меню:

  • visibility = 'authorized' — пункт скрыт для гостей
  • visibility = 'unauthorized' — пункт скрыт для залогиненных пользователей
  • condition (JSON) — произвольные условия: группы пользователей, регион, параметры запроса
class VisibilityChecker { public function isVisible(array $item): bool { global $USER; if ($item['VISIBILITY'] === 'authorized' && !$USER->IsAuthorized()) return false; if ($item['VISIBILITY'] === 'unauthorized' && $USER->IsAuthorized()) return false; $condition = $item['CONDITION'] ?? []; if (!empty($condition['user_groups'])) { $userGroups = $USER->GetUserGroupArray(); if (!array_intersect($condition['user_groups'], $userGroups)) return false; } return true; } } 

Условия видимости применяются уже после получения кешированного дерева — кеш хранит полное дерево, фильтрация происходит в памяти.

Мегаменю с колонками и баннерами

Для пунктов верхнего уровня можно настроить мегаменю-дропдаун с колонками:

[Каталог] ├─ Колонка 1: Электроника │ ├─ Смартфоны │ ├─ Ноутбуки │ └─ Планшеты ├─ Колонка 2: Бытовая техника │ ├─ Холодильники │ └─ Стиральные машины └─ Баннер: [Акции недели → /sale/] 

Колонки хранятся в b_vendor_menu_column, баннеры — в b_vendor_menu_banner. Компонент генерирует HTML-структуру мегаменю, стилизация — через CSS Grid.

Drag-and-drop интерфейс

Административный интерфейс построен на библиотеке Sortable.js. Пункты перетаскиваются в нужную позицию и в нужный родительский элемент. При перетаскивании AJAX-запрос обновляет sort и parent_id одной транзакцией.

Активный пункт

Активный пункт меню определяется по текущему URL:

// Точное совпадение URL или совпадение начала пути function isActive(array $item, string $currentUrl): bool { if ($item['URL'] === $currentUrl) return true; if ($item['URL_TYPE'] === 'section' && str_starts_with($currentUrl, $item['URL'])) return true; return false; } 

Активный пункт и все его предки получают CSS-класс active.

Сравнение со стандартным компонентом

Критерий Стандартный bitrix:menu Наш модуль
Управление из админки Только через файлы Через визуальный drag-and-drop
Мегаменю Требует ручной разметки Встроенные колонки и баннеры
Кэширование Файловое, без тегов Тегированное, инвалидация по событиям
Видимость по группам Только через условие в файле Интерфейс + произвольные условия
Срок внедрения 2-3 дня на настройку 10 дней под ключ

Процесс работы

Мы проходим все этапы от анализа до внедрения:

  1. Аналитика — изучаем структуру каталога, требования к видимости, интеграции.
  2. Проектирование — схемы БД, прототип дерева, согласование с заказчиком.
  3. Разработка — создание ORM-модуля, компонентов, интерфейса админки.
  4. Тестирование — проверка на реальных данных, нагрузочное тестирование.
  5. Внедрение — установка на боевом сайте, настройка кэширования, обучение контент-менеджеров.

Что вы получаете в итоге?

  • Модуль с ORM-таблицами, компонентом для вывода меню, административным интерфейсом.
  • Документация по настройке и использованию.
  • Исходные коды в репозитории.
  • Техническая поддержка в течение 30 дней после запуска.

Сроки разработки

Этап Срок
ORM-таблицы, модель дерева 1 день
Построение дерева, кеширование 1 день
Условия видимости пунктов 1 день
Мегаменю: колонки, баннеры 2 дня
Drag-and-drop интерфейс 2 дня
Компоненты для сайта (HTML + CSS) 2 дня
Тестирование 1 день

Итого: от 10 до 15 рабочих дней в зависимости от сложности.

Оптимизация скорости менюДля ускорения загрузки используйте тегированное кэширование: компонент кэшируется на 3600 секунд с тегом `menu_{code}`. При любом изменении пункта или баннера кэш сбрасывается автоматически через агент. Для больших каталогов (10 000+) рекомендуем включить композитный кэш Битрикс и настроить отложенную загрузку меню через `Bitrix\Main\Page\FrameStatic`.

Подход adjacency list описан в статье Список смежности. Стилизация мегаменю выполняется с помощью CSS Grid.

Наш опыт разработки модулей Битрикс — более 7 лет. Выполнили 50+ проектов по созданию кастомных решений. Гарантируем соблюдение сроков и качество. Свяжитесь с нами для оценки вашей задачи за один день — мы подготовим оптимальное решение. Получите консультацию по проекту: просто напишите нам, и мы обсудим детали.