Разбор и генерация URL
При обработке запрошенного URL, Yii приложение первым делом разбирает URL в маршрут. Полученный маршрут используется при создании соответствующего экземпляра действия контроллера для обработки запроса. Этот процесс называется роутинг.
Обратный роутингу процесс называется Создание URL, он отвечает за создание URL из заданного маршрута и соответствующих параметров запроса. При необходимости, созданный URL всегда может быть преобразован в первоначальные маршрут и параметры запроса.
В основе роутинга и создания URL лежит использование [[yii\web\UrlManager|URL manager]],
зарегистрированного в качестве компонента приложения urlManager
.
[[yii\web\UrlManager|URL manager]] содержит метод [[yii\web\UrlManager::parseRequest()|parseRequest()]]
для разбора входящего запроса на маршрут и параметры запроса, и метод [[yii\web\UrlManager::createUrl()|createUrl()]]
для создания URL из заданного маршрута и параметров запроса.
Настройка компонента urlManager
в конфигурации приложения, позволяет приложению распознавать различные
форматы URL без внесения изменений в существующий код приложения. Например, для
создания URL для действия post/view
, можно использовать следующий код:
use yii\helpers\Url;
// Url::to() вызывает UrlManager::createUrl() для создания URL
$url = Url::to(['post/view', 'id' => 100]);
В зависимости от настройки urlManager
, URL может быть создан в одном из следующих форматов (или любом другом формате). При последующем запросе URL в таком формате, он будет разобран на исходные маршрут и параметры запроса.
/index.php?r=post/view&id=100
/index.php/post/100
/post/100
Форматы URL
[[yii\web\UrlManager|URL manager]] Поддерживает два формата URL: обычный и ЧПУ (человекопонятные URL).
Обычный формат URL использует параметр r
для передачи маршрута и любые другие параметры для передачи остальных параметров запроса. Например, URL /index.php?r=post/view&id=100
задает маршрут post/view
и параметр id
, равный 100. Данный формат не требует специальной конфигурации [[yii\web\UrlManager|URL manager]] и работает с любыми настройками Веб сервера.
Человекопонятный формат URL представляет собой дополнительный путь, следующий за именем входного скрипта, описывающий маршрут и остальные параметров запроса. Например, дополнительный путь в URL /index.php/post/100
- это /post/100
, который может представлять маршрут post/view
и параметр id
со значением равным 100, при наличии соответствующего [[yii\web\UrlManager::rules|правила]]. Для использования ЧПУ, необходимо создать набор правил, соответствующих требованиям к URL.
Переключение между двумя форматами URL осуществляется при помощи свойства [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] компонента [[yii\web\UrlManager|URL manager]] без внесения изменений в код приложения.
Роутинг
Роутинг осуществляется в два этапа. На первом этапе, входящий запрос разбирается в маршрут и параметры запроса. На втором этапе, для обработки запроса создается действие контроллера, соответствующее полученному маршруту.
При использовании простого формата URL, получение маршрута из запроса заключается в получении параметра r
из массива GET
.
При использовании ЧПУ, компонент [[yii\web\UrlManager|URL manager]] ищет среди зарегистрированных [[yii\web\UrlManager::rules|правил]] подходящее для разрешения запроса в маршрут. Если такое правило не найдено, вызывается исключение [[yii\web\NotFoundHttpException]].
После того, как из запроса получен маршрут, самое время создать действие контроллера, соответствующее этому маршруту.
Маршрут разделяется на несколько частей, метками деления служат прямые слеши. Например, маршрут site/index
будет разделен на site
и index
. Каждая из частей представляет собой идентификатор, который может ссылаться на модуль, контроллер или действие. Начиная с первой части маршрута, приложение следует следующему алгоритму для создания модуля (если есть), контроллера и действия:
- Текущим модулем считаем приложение.
- Проверяем, содержит ли [[yii\base\Module::controllerMap|карта контроллеров]] текущего модуля текущий идентификатор. Если содержит, в соответствии с конфигурацией контроллера, найденной в карте, создаем объект контроллера и переходим в п. 5 для обработки оставшейся части маршрута.
- Проверяем, есть ли модуль, соответствующий идентификатору в списке модулей (свойство [[yii\base\Module::modules|modules]]) текущего модуля. Если есть, в соответствии с конфигурацией модуля, найденной в списке модулей, создаем модуль и переходим в п. 2, считая только что созданный модуль текущим.
- Рассматриваем идентификатор как идентификатор контроллера и создаем объект контроллера. Для оставшейся части маршрута выполняем п. 5.
- Контроллер ищет текущий идентификатор в его [[yii\base\Controller::actions()|карте действий]]. В случае нахождения, контроллер создает действие, в соответствии с конфигурацией, найденной в карте. Иначе, контроллер пытается создать встроенное действие, описанное методом, соответствующим текущему идентификатору действия.
При возникновении ошибок на любом из описанных выше этапов, вызывается исключение [[yii\web\NotFoundHttpException]], указывающее на ошибку в процессе роутинга.
Маршрут по умолчанию
В случае, если в результате разбора запроса получен пустой маршрут, вместо него будет использован, так называемый, маршрут по умолчанию. Изначально, маршрут по умолчанию имеет значение site/index
, и указывает на действие index
контроллера site
. Указать свое значение можно при помощи свойства приложения [[yii\web\Application::defaultRoute|defaultRoute]], например так:
[
// ...
'defaultRoute' => 'main/index',
];
Маршрут catchAll
Иногда возникает необходимость временно перевести приложение в режим обслуживания и отображать одно информационное сообщение для всех запросов. Существует много вариантов реализации этой задачи. Но одним из самых простых, является использование свойства [[yii\web\Application::catchAll]], например так:
[
// ...
'catchAll' => ['site/offline'],
];
В данном случае, действие site/offline
будет обрабатывать все входящие запросы.
Свойство catchAll
должно принимать массив, первый элемент которого определяет маршрут, а остальные элементы (пары ключ-значение) определяют параметры, передаваемые действию.
Создание URL
Для создания разных видов URL из заданных маршрутов и параметров, Yii предоставляет метод-помощник [[yii\helpers\Url::to()]]. Примеры:
use yii\helpers\Url;
// создает URL для маршрута: /index.php?r=post/index
echo Url::to(['post/index']);
// создает URL для маршрута с параметрами: /index.php?r=post/view&id=100
echo Url::to(['post/view', 'id' => 100]);
// создает якорный URL: /index.php?r=post/view&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);
// создает абсолютный URL: http://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], true);
// создает абсолютный URL с использованием схемы https: https://www.example.com/index.php?r=post/index
echo Url::to(['post/index'], 'https');
Обратите внимание, что в последнем примере подразумевается использование обычного формата URL. При использовании ЧПУ, будут созданы другие URL, соответствующие [[yii\web\UrlManager::rules|правилам создания URL]].
Маршрут, переданный методу [[yii\helpers\Url::to()]], является контекстно зависимым. Он может быть относительным или абсолютным, в зависимости от следующих правил:
- Если маршрут является пустой строкой, будет использован текущий [[yii\web\Controller::route|маршрут]];
- Если маршрут не содержит слешей вообще, он рассматривается как идентификатор действия текущего контроллера и будет дополнен значением [[\yii\web\Controller::uniqueId|uniqueId]] текущего контроллера в качестве префикса;
- Если маршрут не содержит слеша в начале, он будет рассматриваться как маршрут относительно текущего модуля и будет дополнен значением [[\yii\base\Module::uniqueId|uniqueId]] текущего модуля, в качестве префикса.
Начиная с версии 2.0.2, при составлении маршрутов, стало возможным использовать псевдонимы. В таком случае, псевдоним будет преобразован в маршрут, который будет использован для создания URL по правилам, указанным выше.
Для примера, будем считать, что текущим модулем является admin
, а текущим контроллером - post
,
use yii\helpers\Url;
// запрошенный маршрут: /index.php?r=admin/post/index
echo Url::to(['']);
// относительный маршрут с указанием только идентификатора действия: /index.php?r=admin/post/index
echo Url::to(['index']);
// относительный маршрут: /index.php?r=admin/post/index
echo Url::to(['post/index']);
// абсолютный маршрут: /index.php?r=post/index
echo Url::to(['/post/index']);
// /index.php?r=post/index псевдоним "@posts" определен как "/post/index"
echo Url::to(['@posts']);
В основе реализации метода [[yii\helpers\Url::to()]] лежит использование двух методов компонента [[yii\web\UrlManager|URL manager]]: [[yii\web\UrlManager::createUrl()|createUrl()]] и [[yii\web\UrlManager::createAbsoluteUrl()|createAbsoluteUrl()]]. Ниже будут рассмотрены способы конфигурации [[yii\web\UrlManager|URL manager]] для создания URL в различных форматах.
Метод [[yii\helpers\Url::to()]], так же, поддерживает создание URL не связанных с маршрутами приложения. В данном случае, нужно передать в качестве первого параметра строку, а не массив. Например,
use yii\helpers\Url;
// запрошенный URL: /index.php?r=admin/post/index
echo Url::to();
// URL из псевдонима: http://example.com
Yii::setAlias('@example', 'http://example.com/');
echo Url::to('@example');
// абсолютный URL: http://example.com/images/logo.gif
echo Url::to('/images/logo.gif', true);
Кроме метода to()
, класс [[yii\helpers\Url]] предоставляет и другие удобные методы для создания URL. Например,
use yii\helpers\Url;
// домашний URL: /index.php?r=site/index
echo Url::home();
// базовый URL, удобно использовать в случае, когда приложение расположено в подкаталоге
// относительно корневого каталога Веб сервера
echo Url::base();
// канонический URL запрошенного URL
// подробнее https://support.google.com/webmasters/answer/139066?hl=ru
echo Url::canonical();
// запомнить запрошенный URL и восстановить его при следующих запросах
Url::remember();
echo Url::previous();
Использование человекопонятных URL
Для активации ЧПУ, необходимо настроить компонент urlManager
в конфигурации приложения следующим образом:
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
// ...
],
],
],
]
Свойство [[yii\web\UrlManager::enablePrettyUrl|enablePrettyUrl]] является ключевым, активирует формат ЧПУ. Остальные свойства не обязательные. Однако, в примере выше, показан самый популярный вариант конфигурации ЧПУ.
- [[yii\web\UrlManager::showScriptName|showScriptName]]: это свойство определяет необходимость включения имени входного скрипта в создаваемый URL. Например, при его значении
false
, вместо/index.php/post/100
, будет сгенерирован URL/post/100
. - [[yii\web\UrlManager::enableStrictParsing|enableStrictParsing]]: это свойство позволяет включить строгий разбор URL. Если строгий разбор URL включен, запрошенный URL должен соответствовать хотя бы одному из [[yii\web\UrlManager::rules|правил]], иначе будет вызвано исключение [[yii\web\NotFoundHttpException]]. Если строгий разбор URL отключен и ни одно из [[yii\web\UrlManager::rules|правил]] не подходит для разбора запрошенного URL, часть этого URL, представляющая путь, будет использована как маршрут.
- [[yii\web\UrlManager::rules|rules]]: это свойство содержит набор правил для разбора и создания URL. Это основное свойство, с которым нужно работать, что бы URL создавались в формате, соответствующем требованиям приложения.
Note: Для того, чтобы скрыть имя входного скрипта в создаваемых URL, кроме установки значения свойства [[yii\web\UrlManager::showScriptName|showScriptName]] в
false
, необходимо настроить Веб сервер, чтобы он мог правильно определять PHP скрипт, который должен быть запущен, если в запрошенном URL он не указан явно. Рекомендованные настройки для Apache и Nginx описаны в разделе Установка Yii.
Правила URL
Правила URL - это экземпляр класса [[yii\web\UrlRule]] или класса, унаследованного от него. Каждое правило состоит из шаблона, используемого для поиска пути в запрошенном URL, маршрута и нескольких параметров запроса. Правило может быть использовано для разбора запроса в том случае, если шаблон правила совпадает с запрошенным URL. Правило может быть использовано для создания URL в том случае, если его маршрут и параметры запроса совпадают с заданными.
При включенном режиме ЧПУ, компонент [[yii\web\UrlManager|URL manager]] использует правила URL, содержащиеся в его свойстве [[yii\web\UrlManager::rules|rules]], для разбора входящих запросов и создания URL. Обычно, при разборе входящего запроса, [[yii\web\UrlManager|URL manager]] проверяет все правила в порядке их следования, до первого правила, соответствующего запрошенному URL. Найденное правило используется для разбора URL на маршрут и параметры запроса. Аналогично для создания URL компонент [[yii\web\UrlManager|URL manager]] ищет первое правило, соответствующее заданному маршруту и параметрам и использует его для создания URL.
[[yii\web\UrlManager::rules|Правила]] задаются ассоциативным массивом, где ключи определяют шаблоны, а значения соответствующие маршруты. Каждая пара шаблон-маршрут составляет правило разбора URL. Например, следующие [[yii\web\UrlManager::rules|правила]] определяют два правила разбора URL. Первое правило задает соответствие URL post
маршруту post/index
. Второе правило задает соответствие URL, соответствующего регулярному выражению post/(\d+)
маршруту post/view
и параметру id
.
[
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
Note: Шаблон правила используется для поиска соответствия с частью URL, определяющей путь. Например, в URL
/index.php/post/100?source=ad
путь определяет частьpost/100
(начальный и конечный слеши игнорируются), соответствующая регулярному выражениюpost/(\d+)
.
Правила URL можно определять не только в виде пар шаблон-маршрут, но и в виде массива. Каждый массив используется для определения одного правила. Такой вид определения правил используется в случаях, когда необходимо указать другие параметры правила URL. Например,
[
// ...другие правила URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
По умолчанию, если в конфигурации правила URL не указан явно параметр class
, будет создано правило класса [[yii\web\UrlRule]].
Именованные параметры
Правило URL может содержать несколько именованных параметров запроса, которые указываются в шаблоне в следующем формате: <ParamName:RegExp>
, где ParamName
определяет имя параметра, а RegExp
- необязательное регулярное выражение, используемое для определения значения параметра. В случае, если RegExp
не указан, значением параметра будет любая последовательность символов кроме слешей.
Note: Возможно указание только регулярного выражения для параметров. В таком случае, остальная часть шаблона будет считаться простым текстом.
После разбора URL, параметры запроса, соответствующие шаблону правила, будут доступны в массиве $_GET
через компонент приложения request
.
При создании URL, значения указанных параметров будут вставлены в URL в соответствии с шаблоном правила.
Рассмотрим несколько примеров работы с именованными параметрами. Допустим, мы определили следующие три правила URL:
[
'posts/<year:\d{4}>/<category>' => 'post/index',
'posts' => 'post/index',
'post/<id:\d+>' => 'post/view',
]
При разборе следующих URL:
/index.php/posts
будет разобран в маршрутpost/index
при помощи второго правила;/index.php/posts/2014/php
будет разобран на маршрутpost/index
и параметрыyear
со значением 2014,category
со значениемphp
при помощи первого правила;/index.php/post/100
будет разобран на маршрутpost/view
и параметрid
со значением 100 при помощи третьего правила;/index.php/posts/php
вызовет исключение [[yii\web\NotFoundHttpException]], если [[yii\web\UrlManager::enableStrictParsing]] имеет значениеtrue
, так как правило для разбора данного URL отсутствует. Если [[yii\web\UrlManager::enableStrictParsing]] имеет значениеfalse
(по умолчанию), значениеposts/php
будет возвращено в качестве маршрута.
При создании URL:
Url::to(['post/index'])
создаст/index.php/posts
при помощи второго правила;Url::to(['post/index', 'year' => 2014, 'category' => 'php'])
создаст/index.php/posts/2014/php
при помощи первого правила;Url::to(['post/view', 'id' => 100])
создаст/index.php/post/100
при помощи третьего правила;Url::to(['post/view', 'id' => 100, 'source' => 'ad'])
создаст/index.php/post/100?source=ad
при помощи третьего правила. Параметрsource
не указан в правиле, поэтому он добавлен в созданный URL в качестве параметра запроса.Url::to(['post/index', 'category' => 'php'])
создаст/index.php/post/index?category=php
без использования правил. При отсутствии подходящего правила, URL будет создан простым соединением маршрута, как части пути, и параметров, как части запроса.
Параметры в маршрутах
В маршруте правила URL возможно указание имен параметров. Это позволяет использовать правило URL для обработки нескольких маршрутов. Например, следующие правила содержат параметры controller
и action
в маршрутах.
[
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view',
'<controller:(post|comment)>s' => '<controller>/index',
]
Для разбора URL /index.php/comment/100/create
будет использовано первое правило, которое установит значения параметров controller
равным comment
и action
равным create
. Таким образом, маршрут <controller>/<action>
дубет разрешен в comment/create
.
Аналогично, для маршрута comment/index
, при помощи третьего правила, будет создан URL comment/index
.
Note: Использование параметров в маршрутах позволяет значительно уменьшить количество правил URL и улучшить производительность компонента [[yii\web\UrlManager|URL manager]].
По умолчанию, все параметры, указанные в правиле, являются обязательными. Если запрошенный URL не содержит обязательный параметр, или если URL создается без обязательного параметра, данное правило не будет применено. Свойство [[yii\web\UrlRule::defaults]] позволяет сделать нужные параметры не обязательными. Параметры, перечисленные в данном свойстве, будут иметь заданные значения, в случае если они пропущены.
В следующем правиле описаны необязательные параметры page
и tag
, которые примут значения 1
и пустая строка
в случае, если они будут пропущены.
[
// ...другие правила...
[
'pattern' => 'posts/<page:\d+>/<tag>',
'route' => 'post/index',
'defaults' => ['page' => 1, 'tag' => ''],
],
]
Выше приведенное правило может быть использовано для разбора или создания следующих URL:
/index.php/posts
:page
равно 1,tag
равно ''./index.php/posts/2
:page
равно 2,tag
равно ''./index.php/posts/2/news
:page
равно 2,tag
равно'news'
./index.php/posts/news
:page
равно 1,tag
равно'news'
.
Без использования необязательных параметров понадобилось бы создать 4 правила для достижения того же результата.
Правила с именами серверов
Существует возможность включать имена серверов в шаблон правил URL. Главным образом, это удобно, когда требуется разное поведение приложения, в зависимости от разных имен Веб серверов. Например, следующее правило позволит разобрать URL http://admin.example.com/login
в маршрут admin/user/login
и http://www.example.com/login
в site/login
.
[
'http://admin.example.com/login' => 'admin/user/login',
'http://www.example.com/login' => 'site/login',
]
Также возможно комбинирование параметров и имени сервера для динамического извлечения данных из него. Например, следующее правило позволит разобрать URL http://en.example.com/posts
на маршрут и параметр language=en
.
[
'http://<language:\w+>.example.com/posts' => 'post/index',
]
Note: Правила, содержащие имя сервера, НЕ должны содержать в шаблоне подкаталог пути ко входному скрипту. Например, если приложение расположено в
http://www.example.com/sandbox/blog
, шаблон должен бытьhttp://www.example.com/posts
, вместоhttp://www.example.com/sandbox/blog/posts
. Это позволит изменять расположение приложения без необходимости внесения изменений в его код.
Суффиксы в URL
Компонент предоставляет возможность добавления к URL суффиксов. Например, можно добавить к URL .html
, что бы они выглядели как статические HTML страницы; можно добавить к URL суффикс .json
, для указания на ожидаемый тип данных ответа. Настроить суффиксы в URL можно при помощи соответствующего свойства [[yii\web\UrlManager::suffix]] в конфигурации приложения:
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
],
],
],
]
Данная конфигурация позволяет компоненту [[yii\web\UrlManager|URL manager]] разбирать и создавать URL с суффиксом .html
.
Tip: При установке суффикса
/
, все URL будут заканчиваться слешем.Note: При настроенном суффиксе, все URL не содержащие этот суффикс будут расценены как неизвестные URL. Такое поведение рекомендовано для SEO (поисковая оптимизация).
Иногда возникает необходимость использовать разные суффиксы для разных URL. Добиться этого можно настройкой свойства [[yii\web\UrlRule::suffix|suffix]] у каждого правила. Когда это свойство установлено, оно имеет приоритет перед общей конфигурацией компонента [[yii\web\UrlManager|URL manager]]. Например, cледующая конфигурация содержит правило URL, которое использует .json
в качестве суффикса вместо глобального .html
.
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'suffix' => '.html',
'rules' => [
// ...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
],
],
],
]
HTTP методы
При реализации RESTful API, зачастую бывает необходимость в том, чтобы один и тот же URL был разобран в разные маршруты, в зависимости от HTTP метода запроса. Это легко достигается указанием HTTP методов, поддерживаемых правилом в начале шаблона. Если правило поддерживает несколько HTTP методов, их имена разделяются запятыми. Например, следующие правила имеют шаблон post/<id:\d+>
с разными поддерживаемыми HTTP методами. Запрос PUT post/100
будет разобран в маршрут post/create
, в то время, как запрос GET post/100
будер разобран в post/view
.
[
'PUT,POST post/<id:\d+>' => 'post/create',
'DELETE post/<id:\d+>' => 'post/delete',
'post/<id:\d+>' => 'post/view',
]
Note: Если правило URL содержит HTTP метод в шаблоне, это правило будет использовано только при разборе URL. Такое правило не будет учитываться компонентом [[yii\web\UrlManager|URL manager]] при создании URL.
Tip: Для упрощения маршрутизации RESTful API, Yii предоставляет специальный класс [[yii\rest\UrlRule]], который достаточно эффективен и предоставляет такие удобные возможности, как автоматическое приведение идентификаторов контроллеров к множественной форме. Более подробную информацию можно найти в разделе Веб-сервисы REST Роутинг.
Гибкая настройка правил
В предыдущих примерах, преимущественно, приводились правила URL, заданные парами шаблон-маршрут. Это самый распространенный, краткий формат. В некоторых случаях возникает необходимость более гибкой настройки правил, например указание суффикса при помощи свойства [[yii\web\UrlRule::suffix]]. Пример конфигурации правила URL при помощи массива был рассмотрен в главе Суффиксы в URL:
[
// ...другие правила URL...
[
'pattern' => 'posts',
'route' => 'post/index',
'suffix' => '.json',
],
]
Info: По умолчанию, если в конфигурации правила явно незадан параметр
class
, будет создано правило класса [[yii\web\UrlRule]].
Добавление правил URL динамически
Правила URL могут быть динамически добавлены в компонент [[yii\web\UrlManager|URL manager]]. Часто это необходимо подключаемым модулям для настройки своих правил URL. Для того, что бы динамически добавленные правила могли влиять на процесс роутинга, они должны быть добавлены в процессе предзагрузки. В частности, модули должны реализовываться интерфейс [[yii\base\BootstrapInterface]] и добавлять правила в методе [[yii\base\BootstrapInterface::bootstrap()|bootstrap()]], например:
public function bootstrap($app)
{
$app->getUrlManager()->addRules([
// правила URL описываются здесь
], false);
}
Так же, необходимо включить данный модуль в [[yii\web\Application::bootstrap]], чтобы он смог участвовать в процессе предзагрузки.
Создание классов правил
Несмотря на то, что встроенный класс [[yii\web\UrlRule]] достаточно функционален для большинства проектов, иногда возникает необходимость в создании своего класса правил URL. Например, на сайте продавца автомобилей существует необходимость поддержки URL в таком формате: /Manufacturer/Model
, где и Manufacturer
и Model
должны соответствовать данным, хранящимся в базе данных. Стандартный класс [[yii\web\UrlRule]] не подойдет, так как он рассчитан на работу со статичными шаблонами.
Для решения данной проблемы можно создать такой класс правила URL.
namespace app\components;
use yii\web\UrlRuleInterface;
use yii\base\Object;
class CarUrlRule extends Object implements UrlRuleInterface
{
public function createUrl($manager, $route, $params)
{
if ($route === 'car/index') {
if (isset($params['manufacturer'], $params['model'])) {
return $params['manufacturer'] . '/' . $params['model'];
} elseif (isset($params['manufacturer'])) {
return $params['manufacturer'];
}
}
return false; // данное правило не применимо
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
// Ищем совпадения $matches[1] и $matches[3]
// с данными manufacturer и model в базе данных
// Если нашли, устанавливаем $params['manufacturer'] и/или $params['model']
// и возвращаем ['car/index', $params]
}
return false; // данное правило не применимо
}
}
И использовать новый класс [[yii\web\UrlManager::rules]] при определении правил URL:
[
// ...другие правила...
[
'class' => 'app\components\CarUrlRule',
// ...настройка других параметров правила...
],
]
Производительность
При разработке сложных Веб приложений, важно оптимизировать правила URL так, чтобы разбор запросов и создание URL занимали минимальное время.
Использование параметров в маршрутах позволяет уменьшить количество правил, что значительно увеличивает производительность.
При разборе или создании URL, компонент [[yii\web\UrlManager|URL manager]] проверяет правила в порядке их определения. Поэтому следует более узконаправленные и/или часто используемые правила размещать раньше прочих.
В случае, если несколько правил имеют один и тот же префикс в шаблоне или маршруте, можно рассмотреть использование [[yii\web\GroupUrlRule]], что позволит компоненту [[yii\web\UrlManager|URL manager]] более эффективно обрабатывать правила группами. Часто это бывает полезно в случае, если приложение состоит из модулей, каждый из которых имеет свой набор правил с идентификатором модуля в качестве общего префикса.