Разработка сайта спортивного клуба на 1С-Битрикс
Сайт спортивного клуба — это не корпоративная визитка и не интернет-магазин в привычном понимании. Здесь одновременно работают расписание тренировок, турнирные таблицы, продажа билетов с выбором конкретного места и медиа-портал для болельщиков. Каждый из этих блоков требует отдельной архитектуры данных, а вместе они создают нагрузку, с которой стандартные компоненты Битрикса справляются только при грамотной настройке.
Структура информационных блоков
Для спортивного клуба выстраивается иерархия из нескольких связанных инфоблоков:
- Команды — основной инфоблок с привязкой к виду спорта, лиге, сезону. Свойства: состав (привязка к инфоблоку «Спортсмены»), тренерский штаб, логотип, цвета формы.
- Спортсмены — инфоблок с детализированными профилями: ФИО, амплуа, номер, антропометрия, фото в форме, статистика по сезонам (голы/очки/передачи вынесены в отдельный Highload-блок для быстрой выборки).
-
Матчи и тренировки — Highload-блок (
b_hlblock_schedule), потому что записей за несколько сезонов набирается тысячи. Поля: дата/время, тип (тренировка/матч/товарищеский), команда-хозяин, команда-гость, стадион, статус (запланирован/идёт/завершён/перенесён), счёт. - Турниры — инфоблок с привязкой к сезону. Турнирная таблица формируется кастомным компонентом на основе результатов матчей из Highload-блока.
Привязки между инфоблоками реализуются через свойство типа «Привязка к элементам» (E) или через Highload-справочники, если нужна производительность на выборках.
Расписание: Highload-блок и кеширование
Расписание тренировок и матчей — самый «горячий» раздел сайта. Болельщики заходят проверить ближайшие игры, тренеры смотрят расписание занятий, администраторы обновляют результаты в реальном времени.
Highload-блок выбран не случайно: при 300+ матчах за сезон и 5-6 командах в клубе обычный инфоблок начинает тормозить на сложных фильтрациях. Highload-блок хранит данные в отдельной таблице MySQL, запросы идут напрямую без overhead инфоблочного API.
Фильтрация на фронте: по команде, по типу события, по месяцу. Компонент рендерит календарную сетку с цветовой индикацией — тренировки серым, домашние матчи зелёным, выездные синим. Для SEO каждый матч получает свою детальную страницу с ЧПУ вида /matches/2024-25/spartak-vs-dinamo-12-10/.
Кеш — тегированный, привязан к тегу schedule_updated. При обновлении любого элемента Highload-блока через обработчик события HighloadBlockOnAfterUpdate сбрасывается именно этот тег, а не весь кеш сайта.
Продажа билетов на матчи через модуль sale: SVG-схема зала
Это ключевая и самая технически сложная часть проекта. Стандартный модуль sale в Битриксе заточен под товары в корзине — добавил, оформил, оплатил. Билет на конкретное место в конкретном секторе — совсем другая механика.
Архитектура решения:
Каждый стадион (зал, арена) описывается SVG-файлом, в котором каждое место — отдельный элемент <rect> или <circle> с атрибутами data-sector, data-row, data-seat. SVG загружается в браузер, JavaScript-обработчик отвечает за интерактив: подсветка при наведении, выбор места кликом, отображение занятых мест серым цветом.
Хранение мест и состояний:
Создаётся Highload-блок hl_stadium_seats с полями:
| Поле | Тип | Назначение |
|---|---|---|
UF_STADIUM_ID |
Число | Привязка к стадиону |
UF_SECTOR |
Строка | Код сектора (A, B, C...) |
UF_ROW |
Число | Номер ряда |
UF_SEAT |
Число | Номер места |
UF_CATEGORY |
Справочник | Категория (VIP, стандарт, фан-зона) |
UF_PRICE_ZONE |
Справочник | Ценовая зона |
UF_SVG_ID |
Строка | ID элемента в SVG для сопоставления |
Для каждого матча создаётся таблица бронирований — ещё один Highload-блок hl_ticket_bookings:
| Поле | Тип | Назначение |
|---|---|---|
UF_MATCH_ID |
Число | ID матча из расписания |
UF_SEAT_ID |
Число | ID места из hl_stadium_seats |
UF_STATUS |
Список | free / reserved / sold / blocked |
UF_ORDER_ID |
Число | ID заказа в модуле sale |
UF_RESERVED_AT |
Дата/время | Время бронирования (для автоосвобождения) |
UF_USER_ID |
Число | Покупатель |
Процесс покупки пошагово:
- Пользователь открывает страницу матча, загружается SVG-схема.
- AJAX-запрос к REST-контроллеру получает массив занятых мест для данного матча. JavaScript окрашивает их в серый и убирает обработчик клика.
- Пользователь кликает на свободное место — оно помечается как
reservedвhl_ticket_bookingsс таймштампом. Резерв живёт 15 минут, потом cron-агент (CTicketReserveAgent) обнуляет просроченные. - Выбранные места добавляются в корзину модуля
saleкак товарные позиции. Для этого каждая ценовая зона представлена торговым предложением в каталоге. Свойство корзиныSEAT_INFOхранит сериализованные данные о конкретном месте. - Оформление заказа стандартное —
sale.order.ajaxс кастомизированным шаблоном. При успешной оплате статус меняется наsold, генерируется PDF-билет с QR-кодом через библиотеку TCPDF. - QR содержит подписанный токен (HMAC-SHA256), который проверяется на входе сканером.
Конкурентный доступ — критичный момент. Два болельщика не должны забронировать одно место. Решение: UPDATE ... WHERE UF_STATUS = 'free' с проверкой affected rows. Если вернулся 0 — место уже занято, фронт показывает уведомление и перерисовывает SVG.
Производительность SVG-схемы: стадион на 10 000 мест — это 10 000 DOM-элементов. На мобильных устройствах это вызывает лаги. Оптимизация: Canvas-рендеринг для обзорного вида с переключением на SVG при зуме в конкретный сектор. Либо разбивка по секторам — сначала выбирается сектор на упрощённой схеме, затем загружается детальная SVG только выбранного сектора.
Турнирные таблицы
Кастомный компонент custom:tournament.table агрегирует данные из Highload-блока матчей: считает очки (3 за победу, 1 за ничью), разницу забитых/пропущенных, сортирует. Результат кешируется с тегом tournament_{ID}, сбрасывается при обновлении счёта любого матча в этом турнире.
Для командных видов спорта с плей-офф компонент умеет рендерить сетку play-off (bracket) через SVG — пары, победители, линии связей между раундами.
Профили спортсменов
Детальная страница спортсмена включает: фото, биографию, карьерные достижения (таймлайн через свойство инфоблока «множественное» — клуб, годы, достижения), статистику текущего сезона из Highload-блока, галерею фото/видео с привязкой через CIBlockElement::GetProperty.
Для SEO — микроразметка schema.org/Person с athlete в поле jobTitle, привязка к schema.org/SportsTeam.
Фан-зона и мерч-магазин
Новостной раздел реализуется стандартным компонентом news.list / news.detail с доработанным шаблоном. Фото- и видеогалерея — инфоблок с привязкой к матчам и спортсменам.
Мерч-магазин — полноценный интернет-магазин на модуле catalog + sale: футболки, шарфы, атрибутика. Торговые предложения по размеру и цвету, интеграция с 1С для учёта остатков. Работает параллельно с билетной системой, но в отдельном типе инфоблока, чтобы каталог товаров не пересекался с билетами.
Интеграция с билетными операторами
Если клуб продаёт билеты не только через свой сайт, но и через Ticketland, Kassir.ru или аналогичные системы — нужна синхронизация. Реализуется через REST API билетного оператора: при бронировании/продаже на стороне оператора webhook обновляет статус в hl_ticket_bookings. И наоборот — продажа на сайте отправляет данные оператору.
Cron-агент синхронизации запускается каждые 2 минуты, чтобы подтянуть изменения, которые могли не дойти через webhook (сетевые сбои, таймауты).
Этапы разработки
| Этап | Состав работ | Срок |
|---|---|---|
| Проектирование | Структура инфоблоков, HL-блоков, прототипы SVG-схем | 2–3 недели |
| Вёрстка и фронтенд | Адаптивные шаблоны, интерактивная SVG-схема, календарь | 3–4 недели |
| Бэкенд билетной системы | Модуль бронирования, интеграция с sale, PDF-билеты | 4–5 недель |
| Контент и каталоги | Профили спортсменов, турнирные таблицы, мерч-магазин | 2–3 недели |
| Интеграции | Билетные операторы, 1С, платёжные системы | 2–3 недели |
| Тестирование | Нагрузочное тестирование SVG (10 000 мест), конкурентное бронирование | 1–2 недели |
| Запуск и сопровождение | Деплой, мониторинг агентов, обучение редакторов | 1 неделя |







