Розробка сайту спортивного клубу на 1С-Бітрікс
Сайт спортивного клубу — це не корпоративна візитна картка і не інтернет-магазин у звичному розумінні. Тут одночасно працюють розклад тренувань, турнірні таблиці, продаж квитків з вибором конкретного місця та медіа-портал для вболівальників. Кожен з цих блоків потребує окремої архітектури даних, а разом вони створюють навантаження, з яким стандартні компоненти Бітрікса справляються лише при грамотному налаштуванні.
Структура інформаційних блоків
Для спортивного клубу вибудовується ієрархія з кількох пов'язаних інфоблоків:
- Команди — основний інфоблок з прив'язкою до виду спорту, ліги, сезону. Властивості: склад (прив'язка до інфоблока «Спортсмени»), тренерський штаб, логотип, кольори форми.
- Спортсмени — інфоблок з деталізованими профілями: ПІБ, амплуа, номер, антропометричні дані, фото у формі, статистика за сезонами (голи/очки/передачі винесені в окремий Highload-блок для швидкої вибірки).
-
Матчі та тренування — Highload-блок (
b_hlblock_schedule), тому що записів за кілька сезонів накопичується тисячі. Поля: дата/час, тип (тренування/матч/товариський), команда-господар, команда-гість, стадіон, статус (запланований/йде/завершений/перенесений), рахунок. - Турніри — інфоблок з прив'язкою до сезону. Турнірна таблиця формується кастомним компонентом на основі результатів матчів з Highload-блока.
Прив'язки між інфоблоками реалізуються через властивість типу «Прив'язка до елементів» (E) або через Highload-довідники, якщо потрібна продуктивність на вибірках.
Розклад: Highload-блок і кешування
Розклад тренувань і матчів — найбільш «гарячий» розділ сайту. Вболівальники заходять перевірити найближчі ігри, тренери переглядають розклад занять, адміністратори оновлюють результати в реальному часі.
Highload-блок вибраний не випадково: при 300+ матчах за сезон і 5-6 командах у клубі звичайний інфоблок починає гальмувати на складних фільтраціях. Highload-блок зберігає дані в окремій таблиці MySQL, запити йдуть безпосередньо без навантаження інфоблочного 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 тиждень |







