Сайт санаторію «Березовий гай» на MODX Evolution
Багатомовний сайт радонового курорту в Хмільнику — і внутрішнє рішення, яке позбавило адміністратора головного болю: сквозні змінні цін, що оновлюються по всьому сайту завантаженням одного файлу прайсу.
Клиент: Санаторій «Березовий гай», м. Хмільник, Вінницька обл.
Сайт: sanatory.vn.ua
Платформа: MODX Evolution (PHP + MySQL)
Мови: Українська, російська, англійська, іспанська
Про проєкт
«Березовий гай» — санаторій на радоновому курорті Хмільник, що приймає гостей із лікувальними програмами для опорно-рухового апарату, серцево-судинної та нервової систем. Сайт для такого закладу — це водночас візитівка, медичний довідник і інструмент продажу путівок, тому структура вийшла розгалуженою: розділи про санаторій, лікування та діагностику, категорії номерів від «Стандарту» до двокімнатних люксів із каміном, харчування, дозвілля, відгуки, ціни та бронювання — і все це чотирма мовами.
Завдання
Окрім типових вимог — швидкий сайт, зручна адмінка, багатомовність, презентація номерів і лікувальних програм — замовник озвучив біль, знайомий кожному санаторію, готелю чи медцентру. Ціни змінюються кілька разів на рік: сезонні тарифи, індексація, акції. А згадуються вони не лише на сторінці «Ціни», а й у картках номерів, в описах лікувальних програм, у розділі «Як купити», в акційних банерах. За старого сайту оновлення прайсу перетворювалося на квест: адміністратор вручну проходив десятки сторінок кожною з мов, і завжди щось лишалося непоміченим. Наслідок — розбіжності між сторінками і незручні розмови з гостями, які «бачили на сайті іншу ціну».
Тож ключова технічна вимога сформулювалася так: ціна має існувати на сайті рівно в одному місці, а редактор — мати змогу оновити весь прайс за кілька хвилин без допомоги програміста.
Чому MODX Evolution
MODX Evo обрали свідомо. Це легкий CMF, який не нав'язує структуру: дерево ресурсів природно лягло на розгалужені розділи санаторію, а чанки, сніпети й TV-параметри дали змогу зібрати шаблони без «боротьби з движком». Для адміністратора санаторію Evo-менеджер простий і звичний, а для нас важливо, що будь-яка нестандартна логіка — як-от система цін — пишеться маленьким сніпетом на PHP, без плагінів-комбайнів.

Головне внутрішнє рішення: сквозні змінні цін
Це рішення стане в пригоді будь-якому сайту з прейскурантом — санаторію, готелю, клініці, СТО. Суть проста: жодна ціна не пишеться в тексті сторінки руками. Замість цифри редактор вставляє код ціни, а сама цифра живе в єдиному реєстрі.
1. Єдиний реєстр цін
У базі даних створили окрему таблицю — реєстр цін. Кожна позиція прайсу має унікальний символьний код, значення та службові поля:
CREATE TABLE `site_prices` (
`code` VARCHAR(64) NOT NULL PRIMARY KEY, -- lux2_kamin_single
`value` DECIMAL(10,2) NOT NULL, -- 3250.00
`title` VARCHAR(255) NOT NULL, -- «Люкс 2-кімн. з каміном, 1-місне»
`updated` DATETIME NOT NULL
);
Коди будуються за зрозумілою схемою: категорія номера + варіант розміщення (standart_double, lux1_add_place, child_5_12_main) або назва послуги. Разом із номерним фондом (шість категорій номерів на п'ять варіантів заселення) та додатковими послугами реєстр охоплює весь прейскурант санаторію.
2. Сніпет-плейсхолдер у контенті
Далі — маленький сніпет Price, який можна викликати будь-де: у контенті сторінки, у чанку шаблону, всередині TV-параметра, у виводі Ditto:
[[Price? &code=`lux1_double`]] → 2 400 грн
[[Price? &code=`lux1_double` &raw=`1`]] → 2400
Спрощене ядро сніпета:
db->escape($code) : '';
if ($code === '') return '';
static $prices = null; // один запит на сторінку
if ($prices === null) {
$prices = array();
$rs = $modx->db->select('code, value', $modx->getFullTableName('site_prices'));
while ($row = $modx->db->getRow($rs)) {
$prices[$row['code']] = $row['value'];
}
}
if (!isset($prices[$code])) return '—';
$v = (float)$prices[$code];
if (!empty($raw)) return round($v); // «сире» число для калькуляторів
return number_format($v, 0, ',', ' ') . ' грн';
?php>
?php>
Дрібниця, яка виявилася важливою: сніпет сам форматує суму (розділювач тисяч, нерозривні пробіли, «грн»), тому ціни виглядають однаково на всіх сторінках і всіма мовами — перекладені версії викликають ті самі коди.
3. Одна таблиця прайсу — багато сторінок
Зведена таблиця на сторінці «Ціни» збирається чанком із тих самих плейсхолдерів. Картка кожного номера у розділі «Проживання» показує свою ціну тим самим викликом. Блок «від … грн/доба» на головній — знову він. Коли редактор пише акційний текст «до 31 серпня заселення у "Покращений" за [[Price? &code=`pokr_double`]]», ціна в акції гарантовано збігається з прейскурантом.
4. Оновлення прайсу одним файлом
Найприємніша частина для адміністратора. У менеджері MODX ми зробили простий модуль «Прайс»: сторінка з кнопкою завантаження файлу CSV/Excel. Бухгалтерія санаторію і так веде прейскурант у таблиці — ми лише домовилися про формат: перша колонка — код, друга — ціна, третя — назва для самоперевірки:
code;value;title
standart_single;850;Стандарт, 1-місне заселення
standart_double;1150;Стандарт, 2-місне заселення
lux1_single;2050;Люкс однокімнатний, 1-місне
lux2_kamin_single;3250;Люкс 2-кімн. з каміном, 1-місне
child_5_12_main;900;Діти 5–12 років, основне місце
Модуль працює у два кроки. Спершу — попередній перегляд: файл розбирається, і адміністратор бачить таблицю «код → стара ціна → нова ціна», де зміни підсвічені, а невідомі чи пропущені коди позначені попередженням. Це страхує від найтиповішої помилки — з'їхалих колонок чи одруку в коді. Лише після підтвердження модуль оновлює реєстр однією транзакцією, пише попередню версію прайсу в таблицю історії (можна відкотитися) і чистить кеш сторінок MODX.
Результат для редактора: завантажив файл → переглянув різницю → натиснув «Застосувати». За дві хвилини нові ціни стоять на кожній сторінці сайту, всіма чотирма мовами, без жодного відкритого документа в редакторі.
Що це дає будь-якому сайту з прейскурантом
| Було (ціни в тексті сторінок) | Стало (сквозні змінні) |
|---|---|
| Оновлення прайсу — пів дня ручної роботи по всіх сторінках і мовах | Завантаження одного файлу, 2–3 хвилини |
| Розбіжності: на сторінці номера одна ціна, у прейскуранті інша | Розбіжності неможливі — джерело ціни одне |
| Сезонну зміну тарифів відкладали «до вільного дня» | Нові тарифи публікуються день у день, з позначкою «Ціни діють з …» |
| Помилку помічав гість на рецепції | Помилку ловить попередній перегляд ще до публікації |
Інші рішення проєкту
Багатомовність. Чотири мовні гілки з дзеркальною структурою; сквозні змінні цін тут окупилися подвійно — цифри спільні для всіх мов, перекладаються лише тексти.
Каталог номерів і програм. Картки номерів та лікувальних програм зібрані на TV-параметрах і Ditto: фото, опис, перелік процедур — і ціна через [[Price]].
Заявки та бронювання. Форми «Як купити» з відправкою менеджеру; у листі-заявці ціни підставляються з того ж реєстру, тому менеджер і гість бачать однакові суми.
Швидкість. Кешування MODX плюс єдиний запит реєстру цін на сторінку — сайт лишається легким попри розгалужену структуру.
Підсумок
Санаторій отримав чотиримовний сайт, який адміністратор веде самостійно. А рішення зі сквозними змінними цін перетворило найбільш ризиковану рутину — оновлення прейскуранта — на дві хвилини роботи з одним файлом. Підхід універсальний: реєстр цін, сніпет-плейсхолдер і модуль імпорту можна повторити на будь-якому MODX-сайті (та й не лише на MODX), де ціни розкидані по багатьох сторінках.
?php>?php>
