Yii2. Написание своего правила разбора и построения url

Во всех веб-приложениях, ориентированных на СЕО, невозможно обойтись без реализации ЧПУ. Сегодня я расскажу о том как реализовать произвольный класс построения и разбора url в Yii framework 2.
Допустим у нас есть ActiveRecord-модель Page со следующими полями
id- идентификатор записиparent_id- идентификатор родителяslug- последняя часть урлurl- полный урл без слешей в начале и конце, который формируется как url родителя + '/' + url текущей записиname- название страницыcontent- контент страницыactive- страница активна?
Именно для этой модели мы и будем писать правило разбора. Для этого нам необходимо реализовать интерфейс yii\web\UrlRuleInterface - это всего два метода: createUrl и parseRequest. Метод создания урл и его разбора соответственно.
Создадим класс-заглушку с пустыми методами
class PageRule implements UrlRuleInterface {
public function createUrl($manager, $route, $params){}
public function parseRequest($manager, $request){}
}
И добавим его в список правил урл-менеджера конфигурации веб-приложения.
'components' => [
'urlManager' => [
'rules' => [
// other rules
[
'class' => \app\components\PageRule::class,
],
// other rules
],
],
],
Начнем с написания кода построения урл по id записи. Ниже представлен готовый код с комментариями.
public function createUrl($manager, $route, $params)
{
if ($route !== 'page/show' || isset($params['id']) === false) { // проверяем, что это маршрут для страницы и нам передали id-записи
return false; // return false сообщает UrlManager-у, что мы не смогли построить url и необходимо попробовать применить следующее правило
}
$slug = Page::find() // тут все просто. Это поиск записи в БД.
->select('url')
->where(
[
'id' => $params['id'],
'active' => 1,
]
)
->scalar();
if ($slug !== false) { // если поиск увенчался успехом, то неободимо вернуть найденный урл
return '/' . $slug; // слеш в начале дает знать, что это абсолютный url
}
return false; // мы ничего не нашли в БД :(
}
Отлично. Мы научились строить ссылки. Для этого достаточно вызвать yii\helpers\Url::toRoute(['/page/show', 'id' => 5]) и мы получим url, если в БД присутствует необходимая страница и она активна.
С парсингом url тоже нет проблем. Разберем код.
public function parseRequest($manager, $request)
{
$url = trim($request->pathInfo, '/'); // удаляем слеши из начала и конца url
$page = Page::find() // ищем запись по url
->where(
[
'url' => $url,
'active' => 1,
]
)
->one();
if ($page !== null) { // если нашли, то передаем данные в PageController::actionShow($id). В нем будем рендерить страницу
return ['page/show', ['id' => $page->id]];
}
return false; // сообщаем UrlManager, что ничего не нащли и необходимо попробовать применит следующее правило
}
Вот и все. Как видите, реализовать разбор и построение ЧПУ в Yii2 не так уж и сложно.
P.S. Хочу обратить внимание, что данный пример не учитывает никаких дополнительных GET-параметров при разборе и построении url.
