我在应用程序配置中urlManager
部分,每个路由有多个URL:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
'article-a' => 'article/a', // canonic comes first
'article-deprecated-a' => 'article/a',
'article-another-a-is-deprecated' => 'article/a',
'b-annoucement' => 'announcement/b', // canonic comes first
'legacy-b-annoncement' => 'announcement/b',
...
路由的 SEF URL 以数组形式存储在frontend/config/main.php
中,每个路由有多个 URL。给定路由的第一个 URL(即 /article-a
) 是规范网址,其余网址是旧网址。
为指向同一路由的一组网址指定规范网址的最自然方法是什么?它可以rel="canonical"
视图中,也可以 301/302 重定向到规范网址。
规范 URL 最好指定在定义路由的地方(在本例中为frontend/config/main.php
配置文件)。这里的要求是规范 URL 应在控制器外部定义,而不是硬编码到控制器。
我不确定您需要如何管理您的规则,所以我将选择一个通用用例,我将根据我从 Paddy Moonan 的文章中所理解的内容来回答,我将在以下示例中恢复,我希望它有助于设计所需的解决方案:
要求:
假设搜索引擎确实派了一个机器人来检查我的网站中的page B
,我对人们去page B
而不是page A
并不满意。所以这就是我向机器人澄清我的观点的方法:
-
强制
301
重定向到page A
:告诉搜索引擎此页面被永久移动到页面 A。所以请不要派更多的人去。而是将它们发送到页面 A。
-
强制
302
重定向到page A
:告诉搜索引擎此页面已临时移至页面 A。所以随心所欲是合适的。
-
打开
page B
(200 状态代码),但插入规范链接元素指向page A
:告诉搜索引擎此页面运行良好,但对我来说是辅助页面,我建议将下一个访问者发送到页面A 相反。
设计:
因此,基于此,我将如何看待我的规则配置的可能结构:
'rules' => [
[
// by default: 'class' => 'yii'web'UrlRule',
'pattern' => '/',
'route' => 'site/index',
],
[
// the custom class
'class' => 'app'components'SEOUrlRule',
'pattern' => 'about',
'route' => 'site/about',
'permanents' => [
'deprecated-about',
'an-older-deprecated-about'
],
'temporaries' => [
'under-construction-about',
],
'secondaries' => [
'about-page-2'
]
],
[
// different route with own action but canonical should be injected
'class' => 'app'components'SEOUrlRule',
'pattern' => 'experimental-about',
'route' => 'whatever/experimental',
'canonical' => 'about'
],
]
通过这种方式,我可以根据需要链接尽可能多的数组,以使用 Yii 的默认类 yii''web''UrlRule,同时我可以在我的应用程序组件文件夹中有一个专用于 SEO 相关控制器的自定义数组。
在开始编码之前,这就是我希望我的网站的行为方式:
- 您访问 /about 页面,您会收到
200
响应(否规范添加)。 - 您访问 /deprecated-about 页面,您将被重定向到/关于
301
状态代码。 - 您访问 /正在建设中-关于页面,您将被重定向到/关于
302
状态代码。 - 您访问 /about-page-2 页面,您会得到
200
响应(由index/about
操作呈现)。除了与此类似的标记之外,不会自动将重定向注入源代码:<link href="http://my-website/about" rel="canonical">
- 您访问 /experimental-about 页面,您会得到一个
200
响应(由其自己的操作呈现whatever/experimental
),但上面注入了相同的规范标记。
法典:
SEOUrlRule 将简单地扩展 ''yii''web''UrlRule 并覆盖其 parseRequest 方法来定义额外的属性,我们将基于这些属性在将规范链接标签注册到Yii::$app->view
后强制 HTTP 重定向或调用parent::parseRequest()
:
namespace app'components;
use Yii;
class SEOUrlRule extends 'yii'web'UrlRule
{
public $permanents = [];
public $temporaries = [];
public $secondaries = [];
public $canonical = null;
public function parseRequest($manager, $request)
{
$pathInfo = $request->getPathInfo();
if(in_array($pathInfo, $this->permanents))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 301);
}
else if(in_array($pathInfo, $this->temporaries))
{
$request->setPathInfo($this->name);
Yii::$app->response->redirect($this->name, 302);
}
else if($this->canonical or in_array($pathInfo, $this->secondaries))
{
$route = $this->name;
if ($this->canonical === null) $request->setPathInfo($route);
else $route = $this->canonical;
Yii::$app->view->registerLinkTag([
'rel' => 'canonical',
'href' => Yii::$app->urlManager->createAbsoluteUrl($route)
]);
}
return parent::parseRequest($manager, $request);
}
}
这就是它所需要的。请注意,Yii::$app->controller
或其相关操作在求解路由的早期阶段尚不可用,如本生命周期图所示,但似乎Yii::$app->view
已经初始化,您可以使用其 $params 属性设置自定义参数(如本示例中所做的那样),这对于应共享更多数据或填充更多数据以最终输出的更高级情况可能很有用。
我认为您在创建从应用程序到"article/a"的 URL 时会遇到问题。
为什么不使用 htaccess 或虚拟文件进行 302 重定向到正确的 URL?
如果你想通过urlManager处理它,我想你可以注册规范链接
$this->registerLinkTag(['rel' => 'canonical', 'href' => 'article/a']);
在视图中。模式详情如下: http://www.yiiframework.com/doc-2.0/yii-helpers-baseurl.html#canonical()-detail
Yii2 提供了一个工具,可以根据您的规则生成规范 URL。
'helpers'Url::canonical()
这个想法是,它将为您提供"article-a"的URL。