Yii2:拦截 404 并将 301 重定向到新页面的最佳方法?
Yii2: Best method to intercept 404 and do 301 redirect to new page?
出于 SEO 目的,我想将旧的非 Yii2 URL 重定向到新的。所以我需要拦截 Yii 抛出的 404 并响应 301 重定向。最好的地方在哪里?
我会将旧的 URL 添加到 config/url-manager.php
(或 backend/config/url-manager.php
,如果是高级模板)以通过适当的控制器操作处理它们,并在控制器。
举个例子,假设 pretty URL 被启用,旧的 URL 是 posts/list
而新的简单 posts
,然后将以下内容添加到规则中在 url-manager
:
'posts/list' => 'posts/post/index-redirect',
'posts' => 'posts/post/index',
这会将旧的 URL 路由到帖子模块的 PostController。将以下操作添加到控制器:
public function actionIndexRedirect()
{
return $this->redirect(['index'], 301);
}
当然你可能有很多旧的 URLs 并且你不想一个一个地处理它们,而不是将参数添加到规则并在重定向操作中处理参数。
到目前为止,我自己找到了这些可能的方法:
方法一:
此方法在处理请求之前执行 - 基于已知的 URLs。它们仅在 URL 不直接指向现有 files/folders 时生效(否则 .htaccess
将永远不会将 rquest 重定向到 Yii)。
在 config/web.php
中将以下内容添加到配置数组:
$config = [
'id' => '...',
'components' => '...',
'params' => '...',
...
'on beforeAction' => function($event) {
$redirects = [
'your/old/url.php' => '/my/new-route',
'contact.php' => '/site/contact',
];
if (($newRoute = $redirects[Yii::$app->requestedRoute]) || ($newRoute = $redirects[Yii::$app->requestedRoute .'/'])) {
// maybe you want to add some logging here on this line
Yii::$app->response->redirect(\yii\helpers\Url::to($newRoute), 301);
Yii::$app->end();
}
},
];
方法二:
此方法在在 处理请求后执行 - 基于无路由并以 404 结束。这样做的优点是我们还可以处理未知 URL 以 404 结束。
根据文档 here and here 添加 bootstrap class。然后将其添加到您的 bootstrap() 方法中:
Yii::$app->on(\yii\web\Application::EVENT_BEFORE_ACTION, function($event) use (&$app) {
if ($event->sender->getStatusCode() == 404) {
// maybe you want to add some logging here on this line
if (in_array($app->requestedRoute, ['your/old/url.php', 'contact.php'])) {
// determine new route and redirect the same way as we do in method 1
} else {
// here you do redirect eg. to the homepage or do nothing if you still want to throw a 404
}
}
});
也是另一种变体。
您可以创建一个实现 yii\web\UrlRuleInterface 的 class。该接口需要两个函数:
- parseRequest:使用此方法检查请求是否匹配旧的 url。如果是这样,重定向到新的 url else return false。您可以根据需要检查数据库 table 或旧 url 列表。
- createUrl:因为这些旧的 urls 不再起作用,createUrl 只需要 return false。
public function createUrl($manager, $route, $params)
{
return false; // this rule does not apply
}
此外,我会将此作为 UrlManager 规则的最后一条规则,因此它根本不会影响您的其他页面,无论是性能还是隐藏新 urls。
完整解释见 Yii 文档:https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#creating-rules
出于 SEO 目的,我想将旧的非 Yii2 URL 重定向到新的。所以我需要拦截 Yii 抛出的 404 并响应 301 重定向。最好的地方在哪里?
我会将旧的 URL 添加到 config/url-manager.php
(或 backend/config/url-manager.php
,如果是高级模板)以通过适当的控制器操作处理它们,并在控制器。
举个例子,假设 pretty URL 被启用,旧的 URL 是 posts/list
而新的简单 posts
,然后将以下内容添加到规则中在 url-manager
:
'posts/list' => 'posts/post/index-redirect',
'posts' => 'posts/post/index',
这会将旧的 URL 路由到帖子模块的 PostController。将以下操作添加到控制器:
public function actionIndexRedirect()
{
return $this->redirect(['index'], 301);
}
当然你可能有很多旧的 URLs 并且你不想一个一个地处理它们,而不是将参数添加到规则并在重定向操作中处理参数。
到目前为止,我自己找到了这些可能的方法:
方法一:
此方法在处理请求之前执行 - 基于已知的 URLs。它们仅在 URL 不直接指向现有 files/folders 时生效(否则 .htaccess
将永远不会将 rquest 重定向到 Yii)。
在 config/web.php
中将以下内容添加到配置数组:
$config = [
'id' => '...',
'components' => '...',
'params' => '...',
...
'on beforeAction' => function($event) {
$redirects = [
'your/old/url.php' => '/my/new-route',
'contact.php' => '/site/contact',
];
if (($newRoute = $redirects[Yii::$app->requestedRoute]) || ($newRoute = $redirects[Yii::$app->requestedRoute .'/'])) {
// maybe you want to add some logging here on this line
Yii::$app->response->redirect(\yii\helpers\Url::to($newRoute), 301);
Yii::$app->end();
}
},
];
方法二:
此方法在在 处理请求后执行 - 基于无路由并以 404 结束。这样做的优点是我们还可以处理未知 URL 以 404 结束。
根据文档 here and here 添加 bootstrap class。然后将其添加到您的 bootstrap() 方法中:
Yii::$app->on(\yii\web\Application::EVENT_BEFORE_ACTION, function($event) use (&$app) {
if ($event->sender->getStatusCode() == 404) {
// maybe you want to add some logging here on this line
if (in_array($app->requestedRoute, ['your/old/url.php', 'contact.php'])) {
// determine new route and redirect the same way as we do in method 1
} else {
// here you do redirect eg. to the homepage or do nothing if you still want to throw a 404
}
}
});
您可以创建一个实现 yii\web\UrlRuleInterface 的 class。该接口需要两个函数:
- parseRequest:使用此方法检查请求是否匹配旧的 url。如果是这样,重定向到新的 url else return false。您可以根据需要检查数据库 table 或旧 url 列表。
- createUrl:因为这些旧的 urls 不再起作用,createUrl 只需要 return false。
public function createUrl($manager, $route, $params)
{
return false; // this rule does not apply
}
此外,我会将此作为 UrlManager 规则的最后一条规则,因此它根本不会影响您的其他页面,无论是性能还是隐藏新 urls。
完整解释见 Yii 文档:https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#creating-rules