Yii2:如何使用 UrlManager 重定向到?
Yii2: How to redirect to with UrlManager?
在我的 Yii2 配置中我有:
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'search' => 'site/index',
...
],
...
如果我去 site.com/search
就可以了。如果我转到 site.com/site/index
它也可以工作并显示相同的内容。如何重定向呼叫而不是仅显示 site/index 的响应?它还必须使用参数重定向 (site.com/site/index?param=1
-> site.com/search?param=1
)
UrlManager 不重定向。它宁愿 rewrite like a web server. It is called routing.
如果您想在代码中进行重定向,可以使用 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
事件。您可以在配置数组中执行此操作:
选项 #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;
}
}
]
选项#2
或者如果您有 SearchController
使用:
class SearchController extends \yii\web\Controller {
public function actionIndex() {
$url = 'site/index?' . Yii::$app->request->queryString;
return $this->redirect($url);
}
}
选项 #3
第三个选项是配置网络服务器进行重定向。 这将是最快的解决方案。
您可以使用UrlManager::$enableStrictParsing
来禁用路由匹配。如果您将其设置为 true
,对 /site/index
URL 的请求将不会匹配任何内容,应用程序将 return 404 错误。
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'search' => 'site/index',
// ...
],
// ...
但如果您确实想在其他情况下将路由用作 URL,则这可能不是一个选项。
您可能也对 UrlNormalizer
class 感兴趣。这仍然是一个相对简单的组件并且(还)不支持您的用例,但实际上它是为此类任务而设计的。您可以考虑扩展它并为您的用例添加重定向逻辑 - 它应该比使用事件或专用操作和重定向规则更干净的解决方案。这可能也是一个很好的material 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,
],
// ...
],
],
我认为这会更普适和更普遍。在配置中:
'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;
}
}
}
},
你可以简单地使用redirect
,这更容易,它解决了你的问题,就像render
一样。请参阅以下示例:
return $this->redirect(['/site/index']);
P.S。路径可以是绝对路径或相对路径,您也可以使用别名或其他任何方式,例如:
// an alias of for home page
Yii::setAlias('@home', 'site/index');
在我的 Yii2 配置中我有:
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'search' => 'site/index',
...
],
...
如果我去 site.com/search
就可以了。如果我转到 site.com/site/index
它也可以工作并显示相同的内容。如何重定向呼叫而不是仅显示 site/index 的响应?它还必须使用参数重定向 (site.com/site/index?param=1
-> site.com/search?param=1
)
UrlManager 不重定向。它宁愿 rewrite like a web server. It is called routing.
如果您想在代码中进行重定向,可以使用 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
事件。您可以在配置数组中执行此操作:
选项 #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;
}
}
]
选项#2
或者如果您有 SearchController
使用:
class SearchController extends \yii\web\Controller {
public function actionIndex() {
$url = 'site/index?' . Yii::$app->request->queryString;
return $this->redirect($url);
}
}
选项 #3
第三个选项是配置网络服务器进行重定向。 这将是最快的解决方案。
您可以使用UrlManager::$enableStrictParsing
来禁用路由匹配。如果您将其设置为 true
,对 /site/index
URL 的请求将不会匹配任何内容,应用程序将 return 404 错误。
'components' => [
'urlManager' => [
'baseUrl' => '',
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'search' => 'site/index',
// ...
],
// ...
但如果您确实想在其他情况下将路由用作 URL,则这可能不是一个选项。
您可能也对 UrlNormalizer
class 感兴趣。这仍然是一个相对简单的组件并且(还)不支持您的用例,但实际上它是为此类任务而设计的。您可以考虑扩展它并为您的用例添加重定向逻辑 - 它应该比使用事件或专用操作和重定向规则更干净的解决方案。这可能也是一个很好的material 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,
],
// ...
],
],
我认为这会更普适和更普遍。在配置中:
'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;
}
}
}
},
你可以简单地使用redirect
,这更容易,它解决了你的问题,就像render
一样。请参阅以下示例:
return $this->redirect(['/site/index']);
P.S。路径可以是绝对路径或相对路径,您也可以使用别名或其他任何方式,例如:
// an alias of for home page
Yii::setAlias('@home', 'site/index');