简体   繁体   English

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

[英]Yii2: How to redirect to with UrlManager?

In my Yii2 config I have:在我的 Yii2 配置中,我有:

'components' => [
    'urlManager' => [

        'baseUrl'         => '',
        'enablePrettyUrl' => true,
        'showScriptName'  => false,

        'rules' => [
            'search' => 'site/index',
            ...
        ],
    ...

If I go to site.com/search it works.如果我去site.com/search它工作。 If I go to site.com/site/index it also works and shows the same content.如果我去site.com/site/index它也可以工作并显示相同的内容。 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 )它还必须使用参数重定向( site.com/site/index?param=1 -> site.com/search?param=1

The UrlManager does not redirect. UrlManager 不会重定向。 It rather does a rewrite like a web server.而是像 Web 服务器一样进行重写 It is called routing .它被称为 路由

If you would like to do a redirect in your code you can use Response::redirect() .如果您想在代码中进行重定向,可以使用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.如果您没有SearchController可以将此语句放入操作中,则可以将其放入beforeAction事件中。 You can do this in your configuration array:您可以在配置数组中执行此操作:

Option #1选项1

[
    '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;
        }
    }
]

Option #2选项#2

Or if you have SearchController use:或者,如果您有SearchController使用:

class SearchController extends \yii\web\Controller {
    public function actionIndex() {
        $url = 'site/index?' . Yii::$app->request->queryString;
        return $this->redirect($url);
    }
}

Option #3选项#3

Third option is to configure the web server to do the redirect.第三个选项是配置 Web 服务器来执行重定向。 That would be the fastest solution .那将是最快的解决方案

You may use UrlManager::$enableStrictParsing to disable matching by route.您可以使用UrlManager::$enableStrictParsing来禁用路由匹配。 If you set it to true , request to /site/index URL will not match anything and app will return 404 error.如果您将其设置为true ,则对/site/index URL 的请求将不会匹配任何内容并且应用程序将返回 404 错误。

'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.但是如果你真的想在其他情况下使用路由作为 URL,这可能不是一个选项。


You may also be interested in the UrlNormalizer class.您可能还对UrlNormalizer类感兴趣。 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.它也可能是 PR 并将此功能推送到核心框架的好材料。


Lazy solution would be to create redirection action and add rules to match URLs that needs to be redirect:懒惰的解决方案是创建重定向操作并添加规则以匹配需要重定向的 URL:

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,
        ],
        // ...
    ],
],

You can simply use redirect that's much easier and it solves your problem, it's just like the render .您可以简单地使用更简单的redirect ,它可以解决您的问题,就像render See the example below:请参阅下面的示例:

 return $this->redirect(['/site/index']);

PS The path can be an absolute or relative, you could also use an alias or anything else, here is an example: PS 路径可以是绝对的或相对的,你也可以使用别名或其他任何东西,这是一个例子:

// an alias of for home page
Yii::setAlias('@home', 'site/index');

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;
            }
        }
    }
},

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM