Вопрос: Псевдонимы и канонический URL, или как добиться 301 средствами движка?

Уважаемые коллеги,

Надеюсь, кто-то сможет подсказать, как добиться правильной отработки альтернативных url-ов средствами движка. Я надеюсь, что это возможно, поскольку, заходя на адрес типа site.com/1.html происходит перенаправление с кодом 301 (moved permanently — то, что надо!) на адрес site.com/blog/blog_name/1.html (это можно увидеть по адресной строке браузера, и, например, по инспектору в Хроме).

Странно, что это работает даже когда я убираю соответствующую запись из $config['router']['uri'] в локальном конфиге.

Так вот — я хотел бы добиться того же эффекта для псевдонимов, которые задаю я. Чтобы псевдоним перенаправлял на корректный адрес LS с кодом 301. $config['router']['rewrite'] для этого не подходит, поскольку он полностью убирает один экшин, заменяя его другим. Старый становится недоступен. А вот создание псевдонимов в $config['router']['uri'] справляется с этой задачей наполовину — страница доступна по обоим адресам, но при этом по обоим с кодом 200.

Переход с кодом 301 совершает функция Location в классе Router, есть ли возможность вызывать её для стандартных псевдонимов (понятно, что нахачить можно чего угодно, но зачем, если это уже доступно?).

Заранее благодарю за любую помощь и подсказки!

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

avatar
— Так, я чуть покурил код. Выходит, что Location() просто перебрасывает. А собственно правила рерайта применяются в RewriteRequest()
protected function RewriteRequest($aRequestUrl) {
		/**
		 * Правила Rewrite для REQUEST_URI
		 */
		$sReq=implode('/',$aRequestUrl);
		if($aRewrite=Config::Get('router.uri')) {
			$sReq = preg_replace(array_keys($aRewrite), array_values($aRewrite), $sReq);
		}
		return ($sReq=='') ? array() : explode('/',$sReq);
	}

Дальнейшая обработка идёт стандартно. Копаем глубже.
avatar
Угу, причём в Location (и только в нём, насколько я вижу) безусловно вызывается функция, возвращающая 301 в заголовке:
function func_header_location($sLocation) {  
	header("HTTP/1.1 301 Moved Permanently"); 	
    header('Location: '.$sLocation);
    exit();
}


Поэтому как бы приладить Location к псевдонимам… и почему он вызывается при показе топика по адресу id.html (независимо от настройки псевдонимов, но не вызывается при вызове моих псевдонимов?

Я так понимаю, что хакнуть ядро тут не так и трудно будет (могу ошибаться), но именно хаканья и хотелось бы избежать.
avatar
мне тоже очень насущно надеюсь найти решение.
avatar
Друзья, а чем вас использование rel=«canonical» не устраивает?
avatar
Почитал, подумал. Хм, выходит, можно не беспокоиться о статусе запроса (301 или 200), если везде указать канонический урл, правильно я понимаю?

Если так, то его использование полностью устраивает :) Только, насколько я вижу, он не прописывается для страниц, прописанных в $config['router']['uri']. Вообще, это тянет на прекрасное дополнение к CMS-ке — правильная работа с псевдонимами на полу не валяется. Надо глянуть, может получится патч предложить? :)
avatar
На самом деле сейчас и гугл и яндекс правильно понимают конструкцию rel=«canonical» указанную в шапке страницы, вы можете иметь хоть 10 одинаковых страниц с разными урлами, но если в них правильно указана страница, которая является единственной уникальной и постоянной, то этого достаточно, можно даже не беспокоится про всякие там редиректы и прочую муть, потому что поисковые системы не будут считать что это дубли, так что использование этого тега единственное правильное решение вопроса.
avatar
Да, и это красивое решение, спасибо за идею! (плюсовать местная система не даёт, мал я ещё для этого :))

Только ты так говоришь, будто LS уже это делает. Я пока не вижу, как это сделать — подскажи, пожалуйста, что я упускаю (если упускаю).
avatar
я не думаю, что в ЛС это реализовано, потому что ЛС еще очень молодая система.
Я только сказал идею, что проще ставить на некоторые страницы либо noindex либо canonical для того чтобы избавляться от дублей
avatar
Ух ты, в header.tpl стандартной темы (Synio) есть такая вставка:
{if $sHtmlCanonical}
   <link rel="canonical" href="{$sHtmlCanonical}" />
{/if}

Т.е. что-то таки заложено, в теории. Копаю дальше.
avatar
ну тогда нужно искать откуда происходит и при каких вариантах формируется эта самая переменная $sHtmlCanonical
avatar
Эта переменная устанавливается в классе Viewer в функции SetHtmlCanonical, и применяется (насколько я вижу) исключительно для постраничного вывода — причём почему-то только для первой страницы выставляется canonical (что смотрится крайне странно, но может я не всё понял).

Вызвать эту функцию, чтобы установить канонический урл, в Router::RewriteRequest (где разбирается конфиг псевдонимов) не представляется возможным — потому что объект Viewer на тот момент ещё неинициализирован.

Самое раннее, куда получается его впихнуть, это в Router::Exec, после инициализации объекта Engine (логично). И пока что у меня это получилось только в виде хака (и он работает), но я хочу понять, как это сделать «красиво» — то ли плагином, то ли предложить дописать эту функциональность в ядро.

Я так понимаю, что если делать плагин, то надо переписывать весь класс Router, только пару методов зацепить не получится. Хотелось бы избежать массированного копи-паста.

Надо ещё подумать, если есть идеи — дайте знать.
avatar
Я надеюсь вы смысл этого тега правильно понимаете, вот например на сайте есть 2 разные страницы с одним контентом, обычная страница и страница для печати или вторая часть комментариев, так вот на этой странице и надо указывать что она не главная и говорить, что уникальной является страница с материалом, чтобы небыло дублей на сайте и в индексе поисковой системы.
avatar
Ну я так и понимаю. Поэтому удивляет, что ЛС проставляет этот линк только для первой страницы в пагинации — должно же быть наобророт, на всех остальных, с указанием ссылки на первую?
avatar
если разобраться в ситуации, то по доброму получается, что страницы пагинации например топиков это заголовки материалов с анонсами и по-сути они все не уникальны, но у них нет вообще канонического урла.
Приведу другой пример вот есть лента топиков новая, за 24ч, за неделю, за месяц, по сути это одна и та же лента и даже контент на ней очень похожий, так вот правильнее чтобы яндекс понимал, что лент много, но что они все по сути являются разновидностью ленты «новое» и все вариации урлов ведут в конечном счете на одну новое лента. т.е. все имеют канонический урл который указывает всего лишь на одну, так сказать общую для всех.
avatar
Вообще, в моём случае лучше 301 всё же, потому что речь о перманентном переносе большой пачки урлов (с предыдущей структуры сайтов). Это возможно сделать там же, в ядре, в Router.class.php, только вот пока что не вижу способа внести эти изменения по-человечески, без хаков (спросил тут livestreet.ru/blog/12016.html, но пока что ответ НЕЛЬЗЯ, но надежда умирает последней :)).
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.