Reputation: 1766
In my Yii2 config I have:
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'search' => 'site/index',
...
],
...
If I go to site.com/search
it works. If I go to site.com/site/index
it also works and shows the same content. How to redirect the call instead of just showing the response of site/index? It must also redirect with params (site.com/site/index?param=1
-> site.com/search?param=1
)
Upvotes: 5
Views: 8866
Reputation: 9728
The UrlManager does not redirect. It rather does a rewrite like a web server. It is called routing.
If you would like to do a redirect in your code you can use Response::redirect()
. If you don't have a SearchController
where you can put this statement in an action, you can place it into the beforeAction
event. You can do this in your configuration array:
[
'components' = [
...
],
'on beforeAction' => function ($event) {
if(Yii::$app->request->pathInfo === 'search') {
$url = 'site/index?' . Yii::$app->request->queryString;
Yii::$app->response->redirect($url)->send();
$event->handled = true;
}
}
]
Or if you have SearchController
use:
class SearchController extends \yii\web\Controller {
public function actionIndex() {
$url = 'site/index?' . Yii::$app->request->queryString;
return $this->redirect($url);
}
}
Third option is to configure the web server to do the redirect. That would be the fastest solution.
Upvotes: 5
Reputation: 90
You can simply use redirect
that's much easier and it solves your problem, it's just like the render
. See the example below:
return $this->redirect(['/site/index']);
P.S. The path can be an absolute or relative, you could also use an alias or anything else, here is an example:
// an alias of for home page
Yii::setAlias('@home', 'site/index');
Upvotes: 2
Reputation: 199
I think this will more pricise and lil bit universally. In config:
'components' => [
],
'on beforeAction' => function ($event) {
list($route, $params) = Yii::$app->urlManager->parseRequest(Yii::$app->request);
$params = $_GET;
if (is_string(Yii::$app->request->pathInfo)
&& strpos(Yii::$app->request->pathInfo, $route) === 0
) {
if (strpos($route, '/') === false) {
$route .= '/index';
}
$url = array_merge([0 => $route], $params);
foreach(Yii::$app->urlManager->rules as $rule) {
if ($rule->route === $route) {
Yii::$app->response->redirect($url)->send();
$event->handled = true;
}
}
}
},
Upvotes: 0
Reputation: 22174
You may use UrlManager::$enableStrictParsing
to disable matching by route. If you set it to true
, request to /site/index
URL will not match anything and app will return 404 error.
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'search' => 'site/index',
// ...
],
// ...
But this may be not an option if you actually want to use routes as URLs in other cases.
You may also be interested in the UrlNormalizer
class. This is still a relatively simple component and does not (yet) support your use case, but in fact it was designed for such tasks. You may consider extending it and add redirection logic for your use case - it should be much more clean solution than using events or dedicated actions and rules for redirections. It may be also a good material for PR and pushing this feature to core framework.
Lazy solution would be to create redirection action and add rules to match URLs that needs to be redirect:
class RedirectController extends Controller {
public function actionRedirect($action, $controller, $module = null) {
if ($action === $this->action->id && $controller === $this->id && $module === null) {
// prevent to access action directly and redirection loops
throw new NotFoundHttpException();
}
$url = Yii::$app->request->get();
unset($url['action'], $url['controller'], $url['module']);
array_unshift($url, '/' . ltrim(implode('/', [$module, $controller, $action]), '/'));
return $this->redirect($url);
}
}
And rules:
'urlManager' => [
// ...
'rules' => [
'search' => 'site/index',
[
'pattern' => '<controller:(site)>/<action:(index)>',
'route' => 'redirect/redirect',
'model' => UrlRule::PARSING_ONLY,
],
// ...
],
],
Upvotes: 1