Разработка сайта театра на 1С-Битрикс
У театрального сайта есть проблема, которую не решает ни один шаблонный подход: репертуарная сетка. Один спектакль идёт на трёх площадках, с разным составом, в разные даты, с разными ценами. Зритель хочет выбрать конкретное место в зале, увидеть вид со своего ряда и оплатить билет за 40 секунд. Если хоть одно звено тормозит — он уходит на Афишу или Радарио, где театр отдаёт комиссию с каждого билета.
На 1С-Битрикс такой сайт собирается из связки инфоблоков для контентной части и модуля sale для билетной. Главная инженерная задача — SVG-схема зала с блокировкой мест в реальном времени.
Репертуар и расписание: два инфоблока вместо одного
Частая ошибка — хранить спектакли и показы в одном инфоблоке. Спектакль «Чайка» существует один, а показов — двадцать за сезон. Если на каждый показ дублировать карточку с описанием, фото и составом — получаем контентный хаос и невозможность нормальной фильтрации.
Инфоблок Repertoire — карточка спектакля:
- PROPERTY_GENRE — жанр (драма, комедия, мюзикл, балет, опера — справочник)
- PROPERTY_AGE_RATING — возрастное ограничение (0+, 6+, 12+, 16+, 18+)
- PROPERTY_DURATION — хронометраж с антрактом и без (два числовых поля)
- PROPERTY_PREMIERE_DATE — дата премьеры
-
PROPERTY_DIRECTOR — режиссёр (привязка к инфоблоку
Staff) -
PROPERTY_CAST — основной состав (множественная привязка к
Staff) -
PROPERTY_SCENE — площадка (Основная, Малая, Камерная — привязка к
Venues) - PROPERTY_TRAILER — видеотрейлер (YouTube / Vimeo)
- PROPERTY_GALLERY — фотогалерея (множественный файл)
- PROPERTY_PRESS — рецензии (множественный HTML с источником и цитатой)
- PROPERTY_IN_REPERTOIRE — чекбокс (снятые с репертуара остаются в архиве для SEO)
Инфоблок Schedule — конкретные показы:
| Поле | Тип | Описание |
|---|---|---|
| PROPERTY_SHOW_ID | Привязка | Спектакль из Repertoire |
| PROPERTY_VENUE_ID | Привязка | Зал из Venues |
| PROPERTY_DATETIME | Дата/время | Начало показа |
| PROPERTY_STATUS | Список | В продаже / Мало мест / Продано / Отменён |
| PROPERTY_CAST_OVERRIDE | Множ. привязка | Состав на конкретную дату (если отличается от основного) |
| PROPERTY_PRICE_SCHEME | Привязка | Ценовая схема из HL-блока PriceSchemes |
Связка «один спектакль — много показов» даёт возможность на странице спектакля вывести все ближайшие даты, а в календарной афише — все показы с фильтрацией по дате, жанру и площадке. Компонент bitrix:news.list с фильтром >=PROPERTY_DATETIME по текущей дате и сортировкой по дате — на главную. Прошедшие показы автоматически уходят из афиши, но страница спектакля с фотографиями и рецензиями живёт.
Замена состава на конкретный показ — отдельный нюанс. Если в четверг Гамлета играет основной состав, а в субботу — приглашённый артист, PROPERTY_CAST_OVERRIDE перекрывает основной состав на странице конкретной даты. Зритель видит, кто именно играет в тот вечер, на который он покупает билет.
SVG-схема зала и продажа мест
Технически самый тяжёлый блок. Здесь пересекаются фронтенд (интерактивная карта мест), бэкенд (блокировки, атомарные транзакции) и инфраструктура (Redis для временных блокировок).
SVG-файл зала. Каждый зал — отдельный SVG, где каждое место — элемент с data-атрибутами:
<circle
data-row="7"
data-seat="14"
data-zone="parter"
data-category="A"
cx="312" cy="285" r="6"
class="seat seat--available"
/>
Атрибут data-category привязывает место к ценовой категории. Категории хранятся в HL-блоке SeatCategories: A — центр партера (лучшая видимость), B — боковые секции, C — бельэтаж, D — балкон, E — галёрка. Для каждого показа — своя ценовая сетка. Будний вечер в декабре и субботний предновогодний спектакль — разные деньги за одно и то же место.
SVG-файлы загружаются в инфоблок Venues как свойство PROPERTY_SVG_MAP. Один раз подготовил файл — дальше он используется для всех показов в этом зале.
Интерактив на фронтенде. При открытии страницы покупки:
- Загружается SVG-схема зала из инфоблока
- AJAX-запрос возвращает массив занятых и заблокированных мест для конкретного показа
- JavaScript расставляет классы:
seat--available,seat--occupied,seat--locked,seat--selected - При наведении — tooltip: ряд, место, категория, цена
- При клике — место уходит в корзину, цвет меняется
- Pinch-zoom на мобильных и scroll-zoom на десктопе (библиотека
svg-pan-zoom)
Для залов на 800–1200 мест SVG содержит соответствующее количество элементов. На слабых мобильных устройствах это может тормозить. Решение — отрисовка через Canvas с растеризацией SVG: на экране отображается bitmap, а при зуме — пересчёт области с отрисовкой отдельных мест. Но для залов до 500 мест SVG работает без оптимизаций.
Блокировка мест — Redis. Когда зритель кликает на место, устанавливается временная блокировка. Ключ в Redis: lock:show_{id}:row_{r}:seat_{s} с TTL 600 секунд (10 минут). Перед записью — SETNX: если ключ уже существует, место заблокировано другим покупателем, фронтенд получает ошибку и перерисовывает место как занятое.
Таймер обратного отсчёта виден покупателю: «Места зарезервированы на 8:42». Истекло время — блокировка снимается через TTL автоматически, без cron и агентов.
Почему Redis, а не запись в БД? Потому что TTL-механизм Redis гарантирует освобождение мест даже при падении PHP-процесса. Если пользователь закрыл вкладку — через 10 минут место снова доступно. С записью в b_iblock_element_property пришлось бы писать отдельный агент-чистильщик, который вызывается раз в минуту и проверяет протухшие блокировки. Redis делает это бесплатно.
Серверная обработка покупки:
- Повторная проверка доступности: Redis-блокировка + HL-блок
SoldSeats - Создание заказа в
sale— каждое место как отдельная позиция корзины с ценой по категории - Переадресация на платёжную систему (ЮKassa, CloudPayments, Сбер)
- Обработчик
OnSalePayOrderфиксирует места как проданные вSoldSeats - Генерация PDF-билета с QR-кодом (TCPDF + phpqrcode)
- Отправка на email через модуль
mail
QR-код содержит URL site.ru/ticket/verify/{hash}, где hash — HMAC-SHA256 от ID заказа и секретного ключа. Контролёр на входе сканирует QR, система помечает билет как использованный. Повторный проход — отказ.
Интеграция с билетными системами
Если театр уже работает с Радарио, Ticketland или Яндекс.Афишей — сайт подключается к их API вместо собственной системы продаж:
| Система | Интеграция | Что получаем |
|---|---|---|
| Радарио | REST API v2 | Залы, схемы мест, события, наличие, создание заказа |
| Ticketland | SOAP / REST | Каталог, бронирование, статус оплаты |
| Яндекс.Афиша | Widget API | Виджет продажи с встраиванием на страницу |
| СБИС | REST API | Учёт билетов, фискализация через ОФД |
При работе через API партнёра SVG-схема подтягивается из внешней системы, а не из инфоблока. Адаптер конвертирует формат в единый внутренний — фронтенд работает одинаково в обоих случаях. Если театр решит уйти от Радарио на собственную продажу — переключается адаптер, интерфейс остаётся прежним.
Абонементы и подарочные сертификаты
Абонемент — товар в каталоге sale со свойством «количество посещений» и сроком действия. При покупке создаётся запись в HL-блоке Subscriptions. При бронировании по абонементу списывается одно посещение вместо оплаты.
Подарочный сертификат реализуется через внутренние счета модуля sale. Покупатель оплачивает номинал, получает PDF с уникальным кодом. Получатель активирует код — средства зачисляются на внутренний счёт.
Труппа и архив
Инфоблок Staff: фото, биография, роли (множественная привязка к Repertoire). На странице актёра — список ролей с фото из спектаклей. На странице спектакля — состав с аватарами.
Спектакли, снятые с репертуара, переносятся в архив деактивацией PROPERTY_IN_REPERTOIRE. URL не меняется — SEO сохраняется. Для театра с историей в десятки лет архив даёт сотни проиндексированных страниц с уникальным контентом.
Сроки
| Этап | Длительность |
|---|---|
| Проектирование структуры и UX | 2–3 недели |
| Дизайн (главная, афиша, карточка спектакля, выбор мест) | 3–4 недели |
| Вёрстка и адаптивность | 2–3 недели |
| Программирование инфоблоков и бизнес-логики | 3–4 недели |
| SVG-схемы залов и интерактив покупки | 2–3 недели |
| Интеграция с платёжной / билетной системой | 2–3 недели |
| Контент и тестирование | 2 недели |
| Итого | 16–22 недели |
Параллельная работа дизайнера и разработчика сокращает общий срок на 3–4 недели. При использовании готового API билетной системы (Радарио) этап интеграции уменьшается до 1–2 недель. Стоимость рассчитывается индивидуально после анализа требований — масштаб зависит от количества залов, наличия внешней билетной системы и объёма контента.







