Наверх

Плагин для редиректа если страница перенесена или изменен URL страницы

Надоело мне проставлять вручную редиректы, когда SEO-шники меняют URL (для лучшего соответствия страницы запросам) и просят сделать так, чтобы страница из индекса не вылетела.

Сначала я сделал плагинчик для того, чтобы можно было ресурсы переносить из раздела в раздел безболезненно и добавлять дочерние ресурсы (у контейнеров префикс URL меняется).

Теперь решил поднатужится и сделать максимально автоматизированную систему, которая позволит не только переносить ресурсы, но и менять им псевдонимы, не беспокоясь о редиректах.

Схема и проблемы (теория)


Изначально идеей было сохранять все варианты uri ресурса в отдельную таблицу. Однако пришлось бы на каждом новом сайте создавать таблицу, прописывать схему и пр. Я же хотел, чтобы на каждый новый сайт этот функционал добавлялся как можно проще.

Думаю, как будет время, соберу пакет, который будет сам создавать таблицу и пр.

Пока решил сделать по-другому: при изменении псевдонима создается ресурс, которому устанавливается старый uri.

Тут появляется проблема — если мы захотим поменять псевдоним обратно, вылезет ошибка, так как такой uri уже используется. Я пытался отловить этот момент, чтобы перезаписывать uri второстепенного ресурса. Но здесь видно, что в момент выполнения функции checkFriendlyAlias не вызывается никаких событий (и до этой функции тоже).

Поэтому было решено отключить «проверку на дублирование uri во всех контекстах» (в настройках системы) и создать для второстепенных ресурсов свой контекст.

Сам код и комментарии


И так, сначала по событию OnBeforeDocFormSave мы записываем в сессию текущий uri:
<?php
switch ($modx->event->name) {
  case "OnBeforeDocFormSave":
    if ($mode == 'upd') {
        $uri = $resource->uri;
        $_SESSION[$id."-uri"] = $uri;
    }
    break;
}
После сохранения (событие OnDocFormSave) мы смотрим, изменился ли uri ресурса и если да, то создаем второстепенный ресурс в отдельном контексте:
<?php
switch ($modx->event->name) {
  case "OnDocFormSave":
    if ($mode == 'upd') {
     if ($old_uri == $uri) {break;}
       else {
        $context = "redirector"; // наш контекст
        $uri = $resource->uri;   // текущий uri
        $old_uri = $_SESSION[$id."-uri"]; // uri, записанный в сессию

        // Чтобы дерево ресурсов не разрасталось и админка не тормозила
        // ставим show_in_tree => 0
        $redirectorParams = array(
                 "show_in_tree" => 0
               , "published"    => 1
               , "uri_override" => 1
               , "context_key"  => $context
            );

        $redirectorParams["uri"] = $old_uri;  // Записываем старый uri
        $redirectorParams["longtitle"] = $id; // Указываем, куда редиректить

        $response = $modx->runProcessor('resource/create', $redirectorParams);
        $redirectorId = $response->response['object']['id'];
        $redirector = $modx->getObject("modResource", $redirectorId);
        $redirector->set("pagetitle", $redirectorId);
        $redirector->set("alias",     $redirectorId);
        $redirector->save();
        break;
       }
    }
}
Если мы сначала поменяли псевдоним, а потом решили вернуть его обратно, просто меняем uri ресурсов местами:
<?php
if ($redirector = $modx->getObject("modResource",
                  $redirectorParams)) {
    $redirector->set("uri",$old_uri);
    $redirector->save();
    break;
}
Ну и правила для редиректов (события OnPageNotFound):
<?php
  case "OnPageNotFound":
    $url = $_SERVER['REQUEST_URI'];
    $uri = str_replace($modx->getOption("site_url"),"",$url);
    if (substr($uri, 0, 1) == "/") $uri = substr($uri, 1);
    $redirector = $modx->getObject('modResource', array("uri" => $uri));
    if ($redirector) {
      $modx->sendRedirect($modx->makeUrl($redirector->get('longtitle')),
             array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));
    }

    // Если ресурс не редактировался (например, его просто перетащили в дереве)
    // (это тот самый маленький плагин из прошлой статьи)
    if (substr($url, -5) == ".html") $url = substr($url, 0, -5);
    if (substr($url, -1) == "/")     $url = substr($url, 0, -1);
    $url = str_replace($modx->getOption("site_url"),"",$url);
    $url_array = explode('/', $url);
    $alias = array_pop($url_array);
    $res = $modx->getObject('modResource', array("alias" => $alias));
    if ($res) $modx->sendRedirect($modx->makeUrl($res->get('id')),
              array('responseCode' => 'HTTP/1.1 301 Moved Permanently'));

    break;
}

Инструкция, как запустить на своем сайте


  1. Выключаем в настройках системы global_duplicate_uri_check («Проверять на дублирование URI во всех контекстах»)
  2. Создаем контекст redirector
  3. Создаем плагин и включаем в нем события OnBeforeDocFormSave, OnDocFormSave и OnPageNotFound
  4. Вставляем в плагин код по ссылке.

G+ Оригинал статьи community.modx-cms.ru/blog/tips_and_tricks/9559.html


0 комментариев

    Авторизация

    через сервис Loginza:


    Шаблоны MODX

    1 2 Дальше »

    Объектная
    модель
    MODX