donglang1894
2018-06-03 19:22
浏览 97
已采纳

Yii2:如何使用UrlManager重定向到?

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)

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • doula2426 2018-06-04 07:48
    已采纳

    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 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.

    打赏 评论
  • douyu0845 2018-06-04 09:00

    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,
            ],
            // ...
        ],
    ],
    
    打赏 评论

相关推荐 更多相似问题