Витрина Melbis — это несколько строк в корневом скрипте и дерево модулей, которое разворачивается из одной точки входа. Здесь — общая картина: как устроен путь запроса, из чего состоит проект и как модули складываются в страницу. Подробности каждого звена — в последующих разделах.
index.php
│
├─ require 'units/melbis.php' инициализация окружения: чтение config.json
│ в PHP-константы, обработчики ошибок,
│ автозагрузчик классов, функция MELBIS()
│
├─ MELBIS()->DefineSession(...) сессия посетителя, CSRF-токен,
│ проверка кода включения отладчика
│
├─ MELBIS()->Run($entry_point) запуск модуля входной точки
│ │
│ └─ Parser ─ выполняет PHP-код модуля
│ ─ рендерит его .htm-шаблоны
│ ─ раскрывает вложенные вызовы {MELBIS:...}
│ ─ на каждом уровне проверяет и сохраняет кеш
│
├─ MELBIS()->Publish() вывод готового HTML
│
└─ MELBIS()->Report() панель отладчика, если она включена
Всё, что происходит между Run и Publish, —
работа парсера. Бизнес-логики в корневом скрипте нет: он только решает,
какой модуль запустить первым, и отдаёт результат.
| Что | Где лежит | Раздел |
|---|---|---|
| Корневые скрипты | корень сайта: index.php, cron.php,
.htaccess |
«Корневые скрипты» |
| Модульные скрипты | units/ — файл имя.php на каждый
модуль |
«Модульные скрипты» |
| Шаблоны | templates/{группа}/units/{модуль}/*.htm |
«Синтаксис шаблонов» |
| Настройки | config.json в корне сайта |
«Конфигурация» |
| Движок | core/ — классы платформы и скрипты обмена с
программой |
— |
Ручное подключение файла в проекте ровно одно —
require 'units/melbis.php' в корневом скрипте. Все
остальные зависимости платформа подгружает сама: библиотеки разработчик
отмечает в параметрах модуля, а вложенные модули парсер находит по тегам
в шаблонах.
Каждый модуль формирует фрагмент HTML-кода на основе своих шаблонов. Этот фрагмент может содержать теги вызова других модулей — и так до любой глубины. Парсер обрабатывает всю цепочку автоматически.
Посмотрим на реальный пример из демонстрационного магазина.
Модуль-роутер melbis_base_page запускается как входная
точка и формирует полную страницу. Его главный шаблон
main.htm вызывает три вложенных модуля:
<!doctype html>
<html>
{MELBIS:melbis_base_head()}
<body>
{MELBIS:melbis_base_header()}
<main>
{CONTENT}
</main>
{MELBIS:melbis_base_footer()}
</body>
</html>Модуль melbis_base_header в своём шаблоне, в свою
очередь, вызывает модуль каталога:
<nav>
{MELBIS:melbis_cataloge()}
</nav>А шаблон melbis_cataloge при переборе пунктов меню
вызывает ещё один модуль для подменю, передавая ему [ID]
текущего элемента цикла:
{#MENU}
<li class="nav-item dropdown">
{MELBIS:melbis_cataloge_sub(,,[ID])}
</li>
{MENU#}Параллельно шаблон страницы товаров вызывает модуль списка товаров, тот — карточку каждого товара, а карточка в своём шаблоне вызывает ещё два модуля — изображение и характеристики:
<!-- Шаблон melbis_store_card/main.htm -->
<div class="card">
<h4>{NAME|html}</h4>
{MELBIS:melbis_store_image([ID],kDefault)}
{MELBIS:melbis_store_features([ID])}
...
</div>Таким образом, одна страница магазина может состоять из десятка вложенных модулей — и каждый из них разрабатывается, тестируется и кешируется независимо.
Результат модуля кешируется вместе с его локальными данными — при следующем вызове с теми же параметрами модуль может не выполняться вовсе. Поэтому всё, что зависит от конкретного посетителя, вынесено в отдельный механизм: глобальный массив разворачивается вторым проходом, который не кешируется никогда.
Здесь чаще всего и ошибаются: имя пользователя, содержимое корзины и текущий язык нельзя выводить как обычную переменную модуля — иначе первый же посетитель запечёт своё значение в кеш, и его увидят остальные. Как делать правильно — в разделе «Глобальный массив»; сами уровни кеша — в разделе «Кеширование».