Yii 2 канонический URL в конфигурации urlManager

у меня есть 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) является каноническим, а остальные устаревшие URL-адреса.

каков наиболее естественный способ указать канонический URL-адрес для группы URL-адресов, указывающих на один и тот же маршрут? Это может быть либо rel="canonical" in view или 301/302 перенаправление на canonical URL-АДРЕС.

канонические URL-адреса должны быть предпочтительно указаны в месте, где были определены маршруты (frontend/config/main.php файл конфигурации в этом случае). требование здесь заключается в том, что канонический URL должен быть определен вне контроллера, а не жестко закодирован для контроллера.

3 ответов


я не уверен, как именно вам нужно управлять своими правилами, поэтому я пойду на общий случай использования, и я буду основывать свой ответ на том, что я понял из Пэдди Moogan это который я возобновлю в следующем примере, и я надеюсь, что это поможет при разработке необходимого решения:

требования:

предполагая, что Поисковик направил робот проверить page B на моем сайте, и я не в порядке с людьми, получающими к page B вместо page A. Так вот как я могу прояснить свою точку зрения на робот:

  1. принуждение 301 перейти к page A:

    сообщая поисковой системе, что эта страница постоянно перешел на страницу A. Поэтому, пожалуйста, не отправляйте больше людей на него. Отправить их на страницу, а вместо.

  2. принуждение 302 перейти к page A:

    говорю поисковик эту страницу временное перешел на страницу A. Так что делайте все, что вы думаете уместно.

  3. Открытие page B (200 код состояния), но вставить канонический ссылка элемент указывая на page 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.

прежде чем перейти к коду, вот как я ожидал бы, что мой сайт веди себя прилично:

  • посетить страница вы получаете 200 ответ (нет canonical added).
  • посетить /устаревшие-о страница вы попадаете в с 301 код состояния.
  • посетить /в стадии строительства-около страница вы попадаете в с 302 код состояния.
  • посетить /о-Страница-2 страница вы получаете 200 ответ (вынесенное index/about действие). Никакие перенаправления, кроме аналогичного тега, автоматически не вводятся в исходный код: <link href="http://my-website/about" rel="canonical">
  • посетить /опытно-про страница вы получаете 200 ответ (оказанный своим собственным действием whatever/experimental), но с тем же каноническим тегом выше.

код:

на SEOUrlRule будет просто расширьте \yii\web\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);
    }
}

и это все, что ему нужно. Обратите внимание, что Yii::$app->controller или связанные с ним действия еще не будут доступны на этом раннем этапе решения маршрутов, как показано в этом схема жизненного цикла но, похоже, это Yii::$app->view уже проинициализирован, и вы можете использовать его $params свойство для установки пользовательских параметров (как это делается пример), который может быть полезен для более продвинутых случаев, когда больше данных должно быть общим или заполнено до конечного вывода.


Я думаю, у вас будут проблемы при создании URL-адреса из приложения в "article/a".

почему бы не использовать htaccess или файл vhost для перенаправления 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-адресов canonnical на основе ваших правил.

\helpers\Url::canonical()

идея в том, что он предоставит вам url-адрес 'article-a'.