Маршрутизация — это первостепенная задача фреймворка по обработке входящего запроса. Здесь определяется маршрут, отвечающий за адрес запроса и назначаются дальнейшие действия.
Иногда маршрутизацию во фреймворках называют "роутингом", это одно и то же.
Маршруты проекта составляются разработчиком в файле /routes/map.php, в этот файл могут быть вставлены (инклюдированы) другие файлы с маршрутами из папки "routes", которые вместе и составят карту маршрутизации. Особенностью данных маршрутов стоит считать, что при их загрузке идёт проверка фреймворком на общую правильность и последовательность использованных методов, в случае исключения генерируется ошибка с указанием причины исключения. Так как в карте маршрутов проверке подвергаются все существующие там маршруты, это гарантирует их общую корректность.
После первого запроса или при использовании специальной консольной команды происходит обновление и кеширование маршрутов. Поэтому файлы с маршрутами не должны включать внешний код, только методы класса Route.
Если после проведенных изменений в карте маршрутизации фреймворк не сгенерировал характерных сообщений, то в дальнейшем эти сообщения не будут появляться, по крайней мере до следующих изменений в подключенных файлах маршрутов.
Маршруты определяются методами класса Route, часто используемым из которых является get(). Методы этого класса используются только в карте маршрутизации.
При помощи этого метода можно указать обработку HTTP-метода GET по указанным условиям. Как показано на примере:
Маршрут выведет при обращении к корневому URL сайта строчку "Hello, world!". Чтобы вывести HTML-код (может содержать и PHP-код) из шаблона, метод применяется совместно с функцией view().
Фреймворк HLEB2 обрабатывает произвольные адреса по заданной разработчиком приложения схеме, например:
В указанном случае все адреса URL, отвечающие условной схеме "site.com/resource/.../.../" будут отдавать одинаковую текстовую строчку, а значения "version" и "page" становятся доступны из объекта Hleb\Static\Request: Request::param("version")->asString() и Request::param("page")->asPositiveInt().
Также эти значения можно получить из контейнера и через одноимённые аргументы метода контроллера.
В адресе маршрута допустимо указать, что последняя часть его может отсутствовать:
В случае отсутствия адрес все равно совпадёт с этим маршрутом, но значение 'id' будет равно NULL.
Пример динамического маршрута в котором указаны значения для second и third именованных частей.
Аналогично '/example/{first}/two/three?', только в данных Request будут добавлены к уже имеющемуся динамическому параметру 'first' дополнительные значения ['second' => 'two', 'third' => 'three']. Если конечный параметр отсутствует, то будет равен null.
Множественное назначение маршрутов (в Request::param() окажется нумерованный массив с частями URL):
Фреймворк не позволяет интерпретировать части URL как составные, так как это противоречит стандартам, но из этого правила есть исключение.
Распространена ситуация, когда логин пользователя предваряется специальным тегом @ в URL.
Задать его можно так:
Функция указывает, какой шаблон из папки /resources/views/ соотнести с маршрутом. Пример для файла /resources/views/index.php:
Вторым аргументом функции можно передать переменные в именованном массиве.
Переменные будут доступны в шаблоне.
Для предопределённых адресов '404', '403' и '401' в функции view() будет выведена соответствующая стандартная страница ошибки.
Группировка маршрутов используется для назначения общих свойств маршрутам путем добавления методов к группам, после этого действие метода распространяется на всю группу.
Определение области действия группы обозначается методом toGroup() в начале группы и endGroup() по завершению.
В данном случае метод prefix(), добавленный к группе, распространяет своё действие на все маршруты в ней.
Группы могут быть вложены в другие группы. Также существует альтернативный синтаксис для групп:
Каждому маршруту можно назначить уникальное название.
По этому названию можно генерировать его URL и сделать код независимым от реальных адресов URL.
Это достигается использованием названий вместо адресов.
Например, этот сайт оперирует именами маршрутов для составления ссылок на страницы.
По аналогии с методом get() для HTTP-метода GET, существуют методы post(), put(), patch(), delete(), options() по соответствию с POST, PUT, PATCH, DELETE, OPTIONS.
Эти методы одинаково соответствуют своему HTTP-методу, кроме options().
Во всех остальных случаях метод OPTIONS обрабатывается по стандарту, только в options() можно задать обработку OPTIONS отдельно (переназначить).
Назначенный маршруту, соответствует всем HTTP-методам, в остальном аналогичен get().
Аналогичен методу get(), только имеет дополнительный первый аргумент, в котором можно передать массив с поддерживаемыми HTTP-методами.
Перехватывает все не сопоставленные пути для всех HTTP-методов (или для указанных). Может быть только один метод fallback() в маршрутах для конкретного HTTP-метода.
Таким образом можно назначить соответствие для не найденного совпадения (вместо ошибки 404) для всех типов HTTP-методов или в отдельности.
Для защиты маршрутов от атак типа CSRF предназначен метод protect(). При назначении его к маршруту или группе маршрутов добавляет проверку на наличие специального токена, установленного ранее.
Работает это следующим образом:
На странице выводится токен доступа, можно использовать функцию csrf_token() или csrf_field().
Этот токен передается при помощи JavaScript или в форме вместе с запросом.
Маршрут запроса имеет метод protect() и происходит проверка токена.
Контроллер — часть архитектуры MVC (Action-Domain-Responder для веб), отвечает за дальнейшее управление обработкой запроса, уже идентифицированного маршрутизатором, но не должен содержать бизнес-логику.
Контроллер не может быть использован для группы маршрутов, он назначается конкретному или нескольким по отдельности. Для этого используется метод controller().
В примере первым аргументом указан класс назначаемого контроллера, вторым - используемый метод контроллера.
Метод 'index' можно не указывать, он используется по умолчанию.
Можно заметить, что у метода get() отсутствует уже ненужный с контроллером второй аргумент.
Если контроллер можно назначить только один к маршруту, то посредников (middlewares) может быть несколько, также middleware можно назначить к группе маршрутов.
Метод middleware() означает, что посредник будет выполнен до основного обработчика маршрута. Этому методу есть аналогичный before() и метод after() (выполнится после основного обработчика). Под основным обработчиком здесь подразумевается возвращаемый текст из маршрута, назначенный шаблон или выполнение контроллера.
Назначенные посредники выполняются в той последовательности, в которой расположены.
Аргументы метода для посредника сходны с контроллером, вторым аргументом можно задать выполняемый метод, по умолчанию 'index'. Отличием является наличие третьего аргумента, в нём можно передать массив параметров в middleware. Указанные параметры доступны в методе Hleb\Static\Router::data() или через контейнер.
Модуль — это разновидность контроллера, он указывает в папку /modules/ проекта и содержит название используемого модуля.
Маршрут может содержать динамические части в адресе и методом where() можно установить правила для этих частей.
В этом примере части под названием 'lang', 'user' и 'id' будут проверены с помощью регулярных выражений.
Специальный метод domain() может быть назначен маршруту или группе маршрутов.
Первым аргументом можно указать название домена или поддомена, вторым аргументом уровень соответствия этого правила.
Существует способ, при котором целевой контроллер и метод определяются исходя из значений динамического адреса.
Маршрут в этом случае может быть таким:
В этом примере для URL /page/part/first/ фреймворк попробует определить контроллер как 'MainPartController' и метод 'initFirst'(преобразовав по принципу camelCase).
Принцип подстановки в обработчики должен быть контролируемым, так как в URL могут попасть данные, которые вызовут непредусмотренный заранее контроллер или его метод.
Кроме этого, можно дополнительно указать зависимость от HTTP-метода запроса ключом '[verb]'.
В этом примере для URL /page/example/ фреймворк попробует определить контроллер как 'MainExampleGetController' и метод 'getMethod'(преобразовав по принципу camelCase).
Для метода POST это будут 'MainExamplePostController' и 'postMethod'.
Возможность подстановки может быть особенно полезной при распределении HTTP-методов запроса по методам контроллера.
По умолчанию во фреймворке кеш маршрутов обновляется автоматически после внесения изменений в файл /routes/map.php. Существует также консольная команда для обновления кеша маршрутов:
$php console --routes-upd
Для проекта с большой посещаемостью возможно возникнет надобность отключить в production автоматическое обновление и выполнять перерасчёт кеша маршрутов только консольной командой.
Это делается через настройку 'routes.auto-update' в файле /config/common.php.