20 Май 2011

Решение проблемы постраничной навигации категорий в WordPress

Решение проблемы с навигацией в категориях

Приветствую вас, уважаемый читатель.

Сегодня я поделюсь решением проблемы недоступности страниц категории при использовании ЧПУ (кто не знаком с термином ЧПУ, полезным окажется этот видеоурок по PHP) и плагина WP-PageNavi в движке WordPress.

Суть проблемы:

Ошибка возникает в блогах на движке WordPress со следующим форматом URL статей:

http://name.ru/cat_name/post_name.

Пользователь запросто может убрать имя поста post_name из URL с желанием просмотреть содержимое всей категории cat_name и перейти по ссылке http://name.ru/cat_name.

При этом первая страница постов из категории cat_name отобразится без проблем, а следующие страницы данной категории, переход на которые осуществляется посредством плагина WP-PageNavi (ссылка, для просмотра следующих страниц категории будет иметь вид http://name.ru/cat_name/page/2) отобразят ошибки: Страница не найдена.

Решить данную проблему, обычно, предлагают добавлением хвостика .html после post_name в настройках формата ссылок WordPress (http://name.ru/cat_name/post_name.html). Данное решение подходит только для новых блогов. В случае давно работающих сайтов, с большим количеством проиндесированных поисковиками статей по старым URL, предложенное решение приведет к необходимости переиндексации, что очень нежелательно с точки зрения SEO.

Возникла необходимость заставить нормально функционировать переключение страниц в категориях, сохранив при этом формат ссылок без изменения.

Решение проблемы

Решить данную проблему можно подменой полей REQUEST_URI и REDIRECT_URL суперглобального массива $_SERVER для ссылок вида http://name.ru/cat_name/page/N, где N – натуральное число.

В результате подмены поле должно иметь следующий вид: http://name.ru/category/cat_name/page/N

Постраничная навигация категорий с URL, содержащим кодовое слово category, работает без проблем.

Последовательность действий

  1. Открыть на редактирование в текстовом редакторе файл index.php корневой папки WordPress.
  2. После строки define('WP_USE_THEMES', true); вставить код вызова дополнительной функции myfuckingstub();
  3. В конце документа описать функцию myfuckingstub();
function myfuckingstub()
{
	$uri = $_SERVER['REQUEST_URI'];
	preg_match('/^\/([a-z0-9\-_]+)\/page\/([0-9]+)$/i', $uri, $matches);
	
	if (count($matches) == 0) return;
	
	$uri = '/category/'.$matches[1].'/page/'.$matches[2];
	$_SERVER['REQUEST_URI'] = $uri;
	$_SERVER['REDIRECT_URL'] = $uri;
}

Вот, собственно и все.

Полный код файла index.php после изменений:

define('WP_USE_THEMES', true);
myfuckingstub();

/** Loads the WordPress Environment and Template */
require('./wp-blog-header.php');

function myfuckingstub()
{
	$uri = $_SERVER['REQUEST_URI'];
	preg_match('/^\/([a-z0-9\-_]+)\/page\/([0-9]+)$/i', $uri, $matches);
	
	if (count($matches) == 0) return;
	
	$uri = '/category/'.$matches[1].'/page/'.$matches[2];
	$_SERVER['REQUEST_URI'] = $uri;
	$_SERVER['REDIRECT_URL'] = $uri;
}

Пояснение происходящего

Суперглобальный массив $_SERVER содержит много служебной информации, посмотреть которую можно путем внедрения в файл index.php кода print_r($_SERVER);

Среди разнообразных полей массива будут присутствовать интересующие нас записи:

  • $_SERVER['REQUEST_URI'] – хранит информацию об имени скрипта, обрабатывающего формирование открытой страницы, начиная от корневой директории виртуального хоста и параметры.
  • $_SERVER['REDIRECT_URL'] – хранит адрес редиректа.

Изменение содержимого данных полей приведет к инициализации загрузки страницы по насильно внедренной туда ссылке.

В приведенном коде функции myfuckingstub() 3-я строка получает содержимое поля REQUEST_URI в переменную $uri. Теперь в переменной $uri будет содержаться значащая часть URL, запрошенного пользователем.

4-я строка, посредством PHP-функции preg_match(), проверяет совпадение между содержимым переменной $uri и регулярным выражением /^\/([a-z0-9\-_]+)\/page\/([0-9]+)$/i. Приведенное регулярное выражение кодирует вид ссылок типа http://name.ru/cat_name/page/N (данный вид ссылок встречается только в постраничной навигации категорий, поэтому его можно смело заменить на нужный нам вид http://name.ru/category/cat_name/page/N).

В случае совпадения $uri и регулярного выражения, функция preg_match() вернет массив, состоящий из совпавших частей регулярного выражения (массиву будет присвоено имя $matches).

6-я строка проверяет совпадение по регулярному выражению. Если совпадения нет –  count($matches) будет равен нолю и функция myfuckingstub() завершит свою работу.

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

9 и 10 строки осуществят подмену содержимого соответствующих полей суперглобального массива $_SERVER, что приведет к загрузке страницы по нужной нам ссылке вида http://name.ru/category/cat_name/page/N.

Спасибо за внимание.

С уважением, Андрей Морковин.

MAXCACHE: 0.86MB/0.00039 sec