Основы маршрутизации

В приложении PHP, таком как XF2, нам нужен способ принимать пользовательский запрос для определенного URL-адреса, понимать, какой контроллер, действие и какие данные представляет этот URL-адрес, чтобы можно было представить соответствующий ответ пользователю. Концепция преобразования URL-адреса в местоположение в коде известна как «Маршрутизация».

В XF2 маршрутизация почти полностью управляется из одного места в Admin CP. Это расположение - Admin CP > Development > Routes. Маршруты сгруппированы по одному из двух типов: Публичный и Административный, и они обеспечивают маршрутизацию запросов в Публичных и Административных приложениях соответственно.

Простой пример

На странице маршрутов (смотрите выше) вы должны увидеть запись, указанную для account/. Это публичный маршрут, обеспечивающий маршрутизацию запросов к URL-адресу index.php?account/. Этот конкретный маршрут довольно прост; он состоит только из небольшого количества настроек. Примечательно, что он состоит из «префикса маршрута», контекста раздела и класса контроллера. Давайте разберемся с этими битами более подробно:

Префикс маршрута

Префикс маршрута - это, по сути, бит после index.php? и перед первым /. Это первый шаг в определении того, к какому контроллеру направить запрос.

Контекст раздела

Контекст раздела сообщает навигационным системам в XF, какой элемент навигации следует выбрать, когда посетитель просматривает страницу, на которую направлен этот маршрут. Для общедоступных маршрутов контекстом раздела должен быть идентификатор навигационной записи верхнего уровня. Для маршрутов администратора это должно относиться к идентификатору наиболее конкретной записи навигации администратора (независимо от глубины).

В случае маршрута учетной записи контекст раздела не обязательно применяется по умолчанию, потому что у нас нет вкладки навигации «учетная запись». Но, чтобы увидеть это в действии, просто измените здесь значение «Контекст раздела» на «форумы», сохраните изменения и перейдите в свою учетную запись во внешнем интерфейсе. Теперь вы должны увидеть, что выбрана вкладка навигации «Форумы»!

Контроллер

Это имя класса контроллера, который должен вызываться, когда запрос соответствует этому маршруту. В случае маршрута "account/" мы указываем XF:Account. Это загрузит контроллер учетной записи. (Смотрите Краткие имена классов для получения дополнительной информации). Код для этого находится в следующем месте src/XF/Pub/Controller/Account.php. Обратите внимание, как короткие имена классов могут преобразовываться в "infix", а также в префикс (XF) и суффикс (Account). В этом случае инфикс для этого контроллера (Pub) выводится из типа маршрута Account (публичный).

Действия контроллера

Выше мы объяснили, как маршрут сопоставляется с конкретным контроллером, но мы еще не знаем, как вызывается конкретное действие в этом контроллере. Контроллеры - это, по сути, классы, которые содержат несколько методов действий, и это часть URL-адреса после префикса маршрута, который указывает действие контроллера. Учитывая URL-адрес index.php?account/account-details, вы должны быть перенаправлены к классу XF\Pub\Controller\Account и методу с именем actionAccountDetails(). Если маршрут не определяет действие, то вызывается метод просто actionIndex().

вы можете узнать больше о контроллерах в разделе Основы работы с контроллерами.

Более сложный пример (форматы маршрута)

Давайте посмотрим на маршрут members/. Этот маршрут по-прежнему довольно прост, как маршрут account/, но в нем заполнено дополнительное поле; «Формат маршрута». Чтобы понять, как это работает, взгляните на свой собственный профиль пользователя в интерфейсе пользователя. URL-адрес этого профиля будет выглядеть примерно так: index.php?members/your-name.1. В частности, обратите внимание на часть your-name.1. Это та часть, которую мы пытаемся сопоставить, используя «Формат маршрута».

«Формат маршрута» позволяет нам извлекать данные из URL-адреса запроса, чтобы мы могли передать эту информацию в действие контроллера, чтобы действие могло загружать определенную информацию; в этом случае загружаются сведения о запрошенном профиле пользователя. Это также помогает нам строить ссылки на основе переданных данных. Вот синтаксис:

:int<user_id,username>/:page

Здесь интересно отметить, что важной частью URL-адреса профиля для поиска профиля является не кусок your-name, а фактически идентификатор пользователя (1). Чтобы продемонстрировать это, измените URL-адрес и замените your-name на not-your-name. вы увидите, что найден правильный профиль, и выполняется перенаправление на правильный URL.

Приведенный выше формат указывает, что это параметр на основе целого числа. Для создания исходящей ссылки мы извлекаем целое число из ключа user_id переданных данных. Если в данные передается ключ имени пользователя, он будет "slugified" и добавлен к целочисленному идентификатору, как вы видите в URL-адресе Вашего профиля. Для сопоставления входящего URL-адреса это превращается в регулярное выражение, соответствующее целочисленному формату параметра.

:page - это ярлык для создания части ссылки page-123. В этом случае он ищет страницу в параметрах ссылки. Если он найден, он помещается в URL-адрес, а затем удаляется из параметров. Для входящего синтаксического анализа, если он совпадает (он может быть пустым), он добавит номер страницы к параметрам, передаваемым в контроллер.

Параметры маршрута

Когда маршрут соответствует определенному контроллеру и действию, любые параметры в URL-адресе упаковываются в специальный объект, который мы называем ParameterBag. Этот объект специально разработан для разделения обычных параметров URL-адресов с параметрами, полученными при сопоставлении маршрута. Объект ParameterBag передается в каждое действие контроллера и используется следующим образом:

$userId = $params->user_id;

Sub-names

Также возможно разделить маршруты на другие sub-names. вы можете увидеть это в действии, посмотрев на маршрут members/following. В этом примере following - это sub-name маршрута members. Обычно URL-адрес выглядит как index.php?members/following, часть following указывает действие и просто совпадает с обычным маршрутом members/. Однако, если есть маршрут, который соответствует префиксу "members" и последующему "sub-name", он будет использоваться вместо него. Это верно здесь, поэтому он создает ссылку, подобную следующей:

members/:int<user_id,username>/following/:page

Для сопоставления входящего маршрута этот маршрут будет протестирован перед маршрутом основных участников; если он совпадает, он будет использован.

Эта система sub-name позволяет изменять поведение, например изменять положение параметров или группировать маршруты на разные контроллеры или с разными параметрами. вы можете увидеть пример последнего в дополнениях Resource Manager и Media Gallery.