понедельник, 15 сентября 2014 г.

Как избавиться от знака вопроса в редиректе, если он стоит не после index.php


Сегодня статья не совсем о SEO.
Статья от web разработчика: Антона Филинкова.

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


Не буду нагружать, а перейду к делу – задача:

Сделать редирект 301, в котором был знак вопроса такого типа:


g590407-beton?view_as=list
g590407-beton?view_as=gallery

Как все знают, редирект 301 не работает со знаком вопроса, т.к. обработчик работает только до знака вопроса:

Redirect 301 /g590407-beton?view_as=gallery http://site.com.ua/produktsiya/beton   (1)
Redirect 301 /g590407-beton?view_as=list http://site.com.ua/produktsiya/beton  (2)
И (1) и (2) не осуществят редирект.

А вот такого типа работает
Redirect 301 /g590407-beton http://site.com.ua/produktsiya/beton  (3)

Запомните этот редирект (3), т.к. он нам ещё пригодиться.

Решение проблем знака вопроса


На просторах интернета было найдено довольно много материала и вот решение знака вопроса после index.php:

RewriteCond %{QUERY_STRING} ^id=21:kolodets-iz--kolodeznykh-kolets$ [NC]   (4)
RewriteRule index.php http://site.com.ua/articles/21-kolodets-iz--kolodeznykh-kolets? [R=301,L] (5)

Работает великолепно, есть его альтернатива, которая тоже работает, представлена ниже:
RewriteCond %{QUERY_STRING} ^id=21:kolodets-iz--kolodeznykh-kolets$   (6)
RewriteRule ^index\.php$ http://site.com.ua/articles/21-kolodets-iz--kolodeznykh-kolets? [R=301,L] (7)

Но вот у меня возникла задача, когда знак вопроса не стоит после файла index.php, и над решением этой проблемы утрачено много рабочих часов. Так же найдено в интернете как это сделать через те же правила, но и тот метод не подошел, увы. Метод, представленный выше, не работал вообще (это я выяснил позже). И самое интересное, что в строке после редиректа появлялась запись следующего характера:

http://site.com.ua/produktsiya/beton?view_as=gallery  (8)
либо
http://site.com.ua/produktsiya/beton?view_as= list  (9)

Методом проб и ошибок, я перебрал все возможные варианты построения, придумывал свои, благо есть где посмотреть за что какой символ отвечает. И в итоге решил написать с нуля редирект. И вот тут выяснилось, что из трех прописанных редиректов работал один и он выводил запись (9). А именно редирект (3):

Redirect 301 /g590407-beton http://site.com.ua/ produktsiya/ beton

Плюнув на всё, взял почитал про некоторые php функции,  да и написал редирект, вставил его в шаблон страницы в самое начало, перед выводом всего, что только можно, и радоваться нарадоваться не мог. Работает.

Сам код:



По коду и что он делает.

Сперва, в переменную $getURI присваивает значение URI. Вторая и третья ($newURI) переменные ищут в $getURI совпадение строк, функция str_replace, с кодом ?view_as=list и ?view_as=gallery, и производит замену на пустое место (не пробел) и мы получаем необходимое значение URI.  Соответственно, не найдя их в URI, замена не будет проводиться, круто, php рулит!

Далее, идет сравнение нового URI со старым, не изменённым нами, и если условие не выполняется, то срабатывает функция header (), и выполняет нужный нам редирект, который мы прописали ранее (3). Вуаля, в адресной строке мы видим:

/g590407-beton – а это отработает наш редирект (3) и в итоге полученная нами страница:
http://site.com.ua/produktsiya/beton

Тот адрес, к которому мы стремились.
Моё решение может кому-то не подойдет, может оно немного индивидуальное, но надеюсь, кому-то будет полезен и полезна эта статья. 

6 комментариев:

  1. Спасибо большое автору за статью. Была такая же проблема, полгода назад, долго копался но так и не получилось. Буду пробовать:)

    ОтветитьУдалить
  2. Хорошая статья, спасибо автору. Сработает ли ваш метод для такого редиректа, в интернете кстати также не смогу ничего найти.
    www.site.com/#!/page ==> www.site.com/page

    ОтветитьУдалить
    Ответы
    1. По идее, должно сработать.

      Пример:

      $getURI = $_SERVER['REQUEST_URI'];
      Мы получаем строку вот такого вида: www.site.com/#!/page

      $newURI = str_replace("#!/", "", $getURI);
      Делаем поиск по шаблону #!/ и замену на пусто (без пробела)

      Получаем: www.site.com/page

      Если у вас есть страница по адресу www.site.com/page, тогда редирект сработает.

      Но если у вас сайт на аяксе и все урлы генерируются таким образом, и вы хотите избавиться от этой вложенности, тогда вряд ли, т.к. у вас не существует целевая страница.

      Удалить
  3. Вставил в свою страницу "page" такой код:



    но ничего не поменялось, в чем может быть ошибка?

    ОтветитьУдалить
  4. $getURI = $_SERVER['REQUEST_URI'];
    $newURI = str_replace("#!/", "", $getURI);
    if ($_SERVER['REQUEST_URI'] !== $newURI){
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: $newURI");
    }

    ОтветитьУдалить
  5. Прошу прощения, немного поспешил с ответом.
    Дело в том что ваш сайт скорее всего работает (работал) на AJAX и ещё в PHP "#" - знак комментирования. То есть строка $getURI = $_SERVER['REQUEST_URI']; видит всего лишь "/" и больше ничего. Поэтому редирект не работает.

    Я бы посоветовал вам посмотреть в сторону редиректа на JS. Гугл, вроде, понимает что это редирект, а не какие-то махинации ( лучше уточнить у Артема - автора блога :) ).

    А в JS что-то типа того необходимо (код обернуть тегом script):

    // Ваш адрес после хеша
    var hash = window.location.hash;

    // Редирект с помощью JS
    if ( hash == "#!/page" ) {
    window.location.replace("http://www.site.com/page")
    }

    ОтветитьУдалить