у меня есть 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"
или 301/302 перенаправить на канонический URL.
Канонические URL-адреса желательно указывать в месте, где были определены маршруты (frontend/config/main.php
файл конфигурации в этом случае). Здесь необходимо, чтобы канонический URL-адрес должен был быть определен вне контроллера, а не жестко задан для контроллера.
Я не уверен, как именно вам нужно управлять вашими правилами, поэтому я пойду на общий случай использования и буду основывать свой ответ на том, что я понял из Статья Пэдди Мугана который я продолжу в следующем примере, и я надеюсь, что это поможет при разработке необходимого решения:
Предполагая Поисковый движок действительно послал робот Проверять page B
на моем сайте, и я не в порядке с людьми, получающими page B
вместо page A
, Вот как я могу уточнить мою точку зрения на робот:
Принуждение 301
перенаправить на page A
:
Сообщаем поисковой системе, что эта страница постоянно переместился на страницу А. Поэтому, пожалуйста, не посылайте больше людей. Вместо этого отправьте их на страницу А.
Принуждение 302
перенаправить на page A
:
Сообщаем поисковой системе, что эта страница временный переместился на страницу А. Так что делай что хочешь
является целесообразным.
открытие 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 по умолчанию юй \ Web \ UrlRule в то время как у меня может быть свой собственный в папке компонентов приложения, посвященный контроллерам, связанным с SEO.
Перед тем, как приступить к написанию кода, я бы ожидал, что мой веб-сайт будет вести себя так:
200
ответ (нет301
код состояния.302
код состояния.200
ответ (предоставленный index/about
действие). Никакие перенаправления, кроме тега, подобного этому, автоматически вставляются в исходный код:<link href="http://my-website/about" rel="canonical">
200
ответ (предоставленный его собственным действием whatever/experimental
) но с тем же каноническим тегом выше вводится. SEOUrlRule будет просто расширяться \ Юй \ 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 предоставляет инструмент для генерации канонических ссылок на основе ваших правил.
\helpers\Url::canonical()
Идея состоит в том, что он предоставит вам ссылку на статью-a.