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

时间:2018-06-03 19:22:51

标签: php yii2 yii2-advanced-app

在我的Yii2配置中,我有:

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

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

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

如果我去site.com/search它就有效。如果我转到site.com/site/index,它也会起作用并显示相同的内容。如何重定向调用而不是仅显示站点/索引的响应?它还必须使用参数(site.com/site/index?param=1 - > site.com/search?param=1

重定向

4 个答案:

答案 0 :(得分:1)

UrlManager不会重定向。它更像是rewrite,就像一个Web服务器。它被称为routing

如果您想在代码中进行重定向,可以使用Response::redirect()。如果您没有SearchController可以将此语句放入操作中,则可以将其放入beforeAction事件事件中。您可以在配置数组中执行此操作:

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

或者如果您SearchController使用:

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

第三个选项是配置Web服务器以执行重定向。那将是最快的解决方案。

答案 1 :(得分:1)

您可以使用UrlManager::$enableStrictParsing来禁用路由匹配。如果您将其设置为true,请求/site/index网址将无法匹配任何内容,应用将返回404错误。

'components' => [
    'urlManager' => [
        'baseUrl' => '',
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'enableStrictParsing' => true,
        'rules' => [
            'search' => 'site/index',
            // ...
        ],
    // ...

但如果你真的想在其他情况下使用路由作为URL,那么这可能不是一个选择。

您可能也对UrlNormalizer课感兴趣。这仍然是一个相对简单的组件,并且(还)不支持您的用例,但实际上它是专为此类任务而设计的。您可以考虑扩展它并为您的用例添加重定向逻辑 - 它应该比使用事件或专用操作和重定向规则更加清晰。它也可能是PR的一个很好的材料,并将此功能推向核心框架。

延迟解决方案是创建重定向操作并添加规则以匹配需要重定向的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);
    }
}

规则:

'urlManager' => [
    // ...
    'rules' => [
        'search' => 'site/index',
        [
            'pattern' => '<controller:(site)>/<action:(index)>',
            'route' => 'redirect/redirect',
            'model' => UrlRule::PARSING_ONLY,
        ],
        // ...
    ],
],

答案 2 :(得分:1)

您可以简单地使用redirect,就像render一样简单,它可以解决您的问题。请参见下面的示例:

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

P.S。路径可以是绝对路径,也可以是相对路径,也可以使用别名或其他任何方式,这是一个示例:

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

答案 3 :(得分:0)

我认为这将更加准确和普遍。在配置中:

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