====== Использование цепочки фильтров для организации Front-Controller ======
===== Что такое цепочка фильтров приложения? =====
Типичное веб-приложение, построенние на базе Limb3 пакета WEB_APP, представляет из себя один класс Application. Например, рассмотрим файл **/www/index.php** из CRUD примера, к которому перенаправляются все запросы к нашему приложению.
process();
?>
index.php по сути подключает настроечный файл setup.php и запускает объект класса lmbWebApplication на исполнение. **lmbWebApplication** - это центральный класс, само приложение. С него начинается обработка запроса пользователя.
Что представляет из себя lmbWebApplication?
Файл limb/web_app/src/lmbWebApplication.class.php:
registerFilter(new lmbHandle('limb/web_app/src/filter/lmbUncaughtExceptionHandlingFilter'));
$this->registerFilter(new lmbHandle('limb/web_app/src/filter/lmbSessionStartupFilter'));
$this->registerFilter(new lmbHandle('limb/web_app/src/filter/lmbRequestDispatchingFilter',
array(new lmbHandle('limb/web_app/src/request/lmbRoutesRequestDispatcher'))));
$this->registerFilter(new lmbHandle('limb/web_app/src/filter/lmbResponseTransactionFilter'));
$this->registerFilter(new lmbHandle('limb/web_app/src/filter/lmbActionPerformingFilter'));
$this->registerFilter(new lmbHandle('limb/web_app/src/filter/lmbViewRenderingFilter'));
}
}
?>
lmbWebApplication - это **цепочка фильтров**, содержащая какой-то предопределенный набор фильтров. lmbWebApplication - это класс-пример, который подходит для весьма простых приложений. В реальных приложениях обычно всегда используются свои собственные подобные классы.
Если вы знакомы с шаблоном проектирования Intercepting Filter, то понять идею цепочки фильтров из Limb3 не составит большого труда.
Итак, **фильтры** являются своеобразными расширениями ядра системы, из них состоит самая "верхняя" (начальная) часть приложения, созданного на базе Limb3. Фильтры выполняют действия, характерные для большинства приложений, но обычно не имеющих никакого отношения к предметной области приложения (различные вспомогательные действия). Например, фильтры могут стартовать сессию, разбирать запрос, проверять права доступа, выдавать закешированный вариант страницы, регистрировать посещение страницы в статистике и т.д. То есть фильтры - это своеобразный [[wp>FrontController]], только в Limb3 он не имеет формы единого класса, а разделен на составляющие, любую из которых можно заменить. Количество фильтров различно от приложения к приложению.
Внутренняя логика каждого фильтра зависит от ситуации. Фильтры самостоятельно принимают решение о том, передавать управление следующим фильтрам или нет. Это позволяет обрывать нормальный ход работы приложения и, например, переносить пользователей на определенные страницы сайта.
Цепочка фильтров реализована в виде [[limb3:ru:packages:filter_chain|пакета FILTER_CHAIN]].
Большинство стандартных фильтров можно найти в пакете WEB_APP limb/web_app/src/filter. Вот список таких фильтров c небольшими описаниями:
^Фильтр^Назначение^
|lmbResponseTransactionFilter|Отсылает данные (заголовки и контент) браузеру после того, как большинство остальных фильтров отработали. Необходим, так как логика приложения может требовать обнуления промежуточно сформированных данных и передачи совсем другого результата браузеру.|
|lmbSessionStartupFilter|Настраивает драйвер хранилища сессионных данных и стартует сессию|
|lmbUncaughtExceptionHandlingFilter|Позволяет обрабатывать ошибки, возникшие в системе и выводить пользователю более "мягкие варианты"|
|lmbRequestDispatchingFilter|В этом фильтре определяется текущий контроллер и действие.|
|lmbActionPerformingFilter|Запускает команду, которая соответствует текущему контроллеру и действию|
|lmbViewRenderingFilter|Запускает процесс рендеринга шаблона, который был установлен в результате выполнения действия контроллера|
===== Связь Запроса, Контроллера и View =====
Как в Limb3 в рамках цепочки фильтров приложения взаимодейтсвуют MVC-компоненты, то есть:
* как приложение определяет, что необходимо делать?
* как осуществляется отработка нужного действия?
* как осуществляется рендеринг шаблона?
* как различные компоненты знают друг о друге?
За первые три пункта этого списка, как вы наверное уже догадались, отвечают соответствующие фильтры:
* **lmbRequestDispatchingFilter**
* **lmbActionPerformingFilter**
* **lmbViewRenderingFilter**
Подробнее [[filter_chain|о фильтрах, применяемых в пакете WEB_APP]]
Сменив или расширив любой из этих фильтров, мы можем изменить любой компонент Limb-приложения:
* Сменить шаблонную систему
* Поменять механизм разбора запроса
* Добавить любые дополнительные проверки, характерные для всех (большинства) вызовов.
Теперь последний вопрос: как различные компоненты знают друг о друге? Для этих целей существует [[limb3:ru:packages:toolkit|тулкит]]!
Тулкит (через [[lmb_web_app_tools|lmbWebAppTools]]) содержит:
* переменную **$view**, которая является объектом класса lmbView (вернее производного от него - скорее всего это будет lmbWactView). $view - является посредником между реальным шаблоном и приложением.
* переменную **$dispatched_controller**, которая является объектом класса lmbController (или дочерним).
* объект **$request** (класс [[limb3:ru:packages:net:lmb_http_request|lmbHttpRequest]], находится в пакете NET) - представляет из себя контейнер со всеми данными, поступившими в зачестве запроса приложению.
* объект **$response** (класс [[limb3:ru:packages:net:lmb_http_response|lmbHttpResponse]], находится также в пакете NET) - представляет из себя ответ приложения на запрос.
Так как тулкит может быть получен в любом месте системы - значит все эти объекты также доступны везде в приложении!
Поэтому:
* lmbRequestDispatchingFilter - использует $request и ставит в тулкит $dispatched_controller.
* lmbActionPerformingFilter - получает из тулкита $dispatched_controller и вызывает метод performAction()
* Контроллер где-то внутри получает $view и ставит в него название шаблона через метод setTemplate($name) (может также передавать во $view некоторые данные)
* lmbViewRenderingFilter - получает $view и вызывает у мего метод render(), а результат рендеринга помещает в $response.
===== См. также =====
* [[limb3:ru:packages:web_app:application_workflow|Схема типичного Limb3 web-приложения, выполненого при помощи пакета WEB_APP]]