【发布时间】:2021-01-15 19:32:08
【问题描述】:
出于 SEO 的目的,我想将旧的非 Yii2 URL 重定向到新的 URL。所以我需要拦截 Yii 抛出的 404 并以 301 重定向响应。最好的地方在哪里?
【问题讨论】:
标签: php yii2 http-status-code-301
出于 SEO 的目的,我想将旧的非 Yii2 URL 重定向到新的 URL。所以我需要拦截 Yii 抛出的 404 并以 301 重定向响应。最好的地方在哪里?
【问题讨论】:
标签: php yii2 http-status-code-301
你可以创建一个实现 yii\web\UrlRuleInterface 的类。该接口需要两个函数:
public function createUrl($manager, $route, $params)
{
return false; // this rule does not apply
}
另外,我会把它作为你的 UrlManager 规则的最后一条规则,这样它就不会影响你的其他页面,无论是性能还是隐藏新的 url。
完整解释请参见 Yii 文档:https://www.yiiframework.com/doc/guide/2.0/en/runtime-routing#creating-rules
【讨论】:
我会将旧 URL 添加到 config/url-manager.php(或在高级模板的情况下为 backend/config/url-manager.php)以通过适当的控制器操作处理它们,并在控制器中进行重定向。
举个例子,假设启用了漂亮的 URL,旧的 URL 是 posts/list,新的 URL 是简单的 posts,然后在 url-manager 的规则中添加以下内容:
'posts/list' => 'posts/post/index-redirect',
'posts' => 'posts/post/index',
这会将旧 URL 路由到帖子模块的 PostController。将以下操作添加到控制器:
public function actionIndexRedirect()
{
return $this->redirect(['index'], 301);
}
当然,您可能有很多旧 URL,并且您不想一个一个地处理它们,而是将参数添加到规则并在重定向操作中处理参数。
【讨论】:
到目前为止,我自己发现了这些可能的方法:
方法一:
此方法在处理请求之前执行 - 基于已知的 URL。它们仅在 URL 不直接指向现有文件/文件夹时生效(否则.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 结尾。这样做的优点是我们还可以处理以 404 结尾的未知 URL .
根据文档 here 和 here 添加引导类。然后将其添加到您的 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
}
}
});
Here 也是另一个变体。
【讨论】: