urlManager配置中的Yii 2规范URL

Est*_*ask 9 php redirect canonical-link yii2 yii2-advanced-app

我有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',
            ...
Run Code Online (Sandbox Code Playgroud)

路由的SEF URL以frontend/config/main.php数组形式存储,每个路由有多个URL.给定路由(即/article-a)的第一个URL 是规范的,其余的是遗留URL.

为一组指向同一路由的URL指定规范URL的最自然的方法是什么?它可以rel="canonical"在视图中或301/302重定向到规范URL.

规范URL应该优选地在定义路由的地方指定(frontend/config/main.php在这种情况下是配置文件).这里的要求是规范URL应该在控制器之外定义,而不是硬编码到控制器.

Sal*_*ani 5

我不确定您需要如何精确地管理自己的规则,因此我将介绍一个通用用例,并将基于我从Paddy Moogan的文章中了解的内容得出答案,我将在以下示例中继续进行,我希望它有助于设计所需的解决方案:

需求:

假设搜索引擎确实派了一个机器人page B登录我的网站,但我对进入page B而不是进入的人们感到不满page A。所以这就是我要阐明对机器人的观点的方法:

  1. 强制301重定向到page A

    告诉搜索引擎该页面已永久移至页面A。因此,请勿派遣更多人到该页面。而是将它们发送到页面A。

  2. 强制302重定向到page A

    告诉搜索引擎该页面是临时的,移至页面A。因此,请执行您认为合适的任何操作。

  3. 开幕page B200状态码),但插入一个规范链接元素 指向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'
    ],
]
Run Code Online (Sandbox Code Playgroud)

这样,我可以使用Yii的默认类yii \ web \ UrlRule链接尽可能多的数组,而我的应用程序组件文件夹中的SEO相关控制器专用自定义数组

在编写代码之前,这就是我期望我的网站表现的方式:

  • 您访问/ about页面时会得到200响应(未添加规范)。
  • 您访问/ deprecated-about页面并使用301状态代码将其重定向到 / about
  • 您访问/ under-construction-about页面并使用302状态代码重定向到 / about
  • 您访问/ about-page-2页面时会收到200响应(index/aboutaction 呈现)。除了与之类似的标记外,没有其他重定向会自动注入源代码: <link href="http://my-website/about" rel="canonical">
  • 您访问/ experimental-about页面,您会收到200响应(通过其自己的操作呈现whatever/experimental),但上面插入了相同的规范标签。

码:

SEOUrlRule会延长\警予\网络\ UrlRule并覆盖其的parseRequest方法来定义基于额外的属性上,我们将强制HTTP重定向或调用parent::parseRequest()规范链接标签注册到后Yii::$app->view

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是它所需要的。请注意,Yii::$app->controller或其相关行动将还没有到可以在,因为它是在这个所示解决途径的早期阶段生命周期图,但似乎Yii::$app->view已经被初始化,您可以使用它的$ PARAMS属性来设置自定义参数(因为它是在此示例中完成),对于更多情况下应该共享或填充更多数据到最终输出的情况可能有用。