Здравствуйте. Потребовалось настроить кастомно маршрутизацию для фильтров на странице.
Фильтр - это форма, которая передает $_GET параметры в соответствии с правилами Yii2 для модели.
Т.е. при применении фильтра url выглядит примерно так: index.html?RoutesSearch[id_district]=9&RoutesSearch[id_region]=10&page=4
Требуется: routes/district/yuzhnyj/region/krym/index.html?page=3
Как реализовал. В первую очередь редирект на правильный URL. Это сделал в контроллере в методе beforeAction()
public function beforeAction($action)
{
if ($action->id == 'index' && stripos(Yii::$app->request->absoluteUrl, 'RoutesSearch')) {
$redirectUrl = Url::base(true).'/routes';
$params = Yii::$app->request->get('RoutesSearch');
if (isset($params['id_district'])) {
$model = District::findOne($params['id_district']);
if ($model)
$redirectUrl .= '/district/'.$model->URI;
}
if (isset($params['id_region'])) {
$model = Regions::findOne($params['id_region']);
if ($model)
$redirectUrl .= '/region/'.$model->URI;
}
if (isset($params['type_id'])) {
$model = RouteTypeNew::findOne($params['type_id']);
if ($model)
$redirectUrl .= '/type/'.$model->URI;
}
if (isset($params['period'])) {
$model = Month::findOne($params['period']);
if ($model)
$redirectUrl .= '/month/'.$model->URI;
}
$redirectUrl .= '/index.html';
if (!empty(Yii::$app->request->get('page'))) {
$redirectUrl .= '?page='.Yii::$app->request->get('page');
}
header('HTTP/1.1 301 Moved Permanently');
header('Location: '.$redirectUrl);
exit();
}
return true;
}
Вторым делом, нужно дать понять Yii к какому контроллеру и экшену такой маршрут отнести и сгенерировать правильные параметры для модели фильтра. Для этого Написал класс для урл менеджера:
class MainFiltersRule implements UrlRuleInterface
{
public function createUrl($manager, $route, $params)
{
return false;
}
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
$partsUrl = explode('/' ,$pathInfo);
if ($partsUrl[0] == 'routes') {
if (in_array('district', $partsUrl)) {
$model = District::find()->where(['URI' => $partsUrl[array_search('district', $partsUrl) + 1]])->one();
$params['RoutesSearch']['id_district'] = $model->id;
}
if (in_array('region', $partsUrl)) {
$model = Regions::find()->where(['URI' => $partsUrl[array_search('region', $partsUrl) + 1]])->one();
$params['RoutesSearch']['id_region'] = $model->id;
}
if (in_array('type', $partsUrl)) {
$model = RouteTypeNew::find()->where(['URI' => $partsUrl[array_search('type', $partsUrl) + 1]])->one();
$params['RoutesSearch']['type_id'] = $model->id;
}
if (in_array('month', $partsUrl)) {
$model = Month::find()->where(['URI' => $partsUrl[array_search('month', $partsUrl) + 1]])->one();
$params['RoutesSearch'][['period']] = $model->id;
}
return ['routes/index', $params];
}
return false;
}
}
Собственно вопрос в том, не совсем ли это извращенно и есть более разумный способ или все-таки вполне себе нормальное решение?
Заранее благодарен всем отозвавшимся.