Предотвращение перенаправления index.php?category_name=something
Я пытаюсь фильтровать записи в категории по году публикации. Также я хочу делать это без перенаправления на шаблон года, поэтому мой идеальный URL будет выглядеть как http://example.com/category/reports/2011/, который должен загружать файл шаблона category.php, где я затем могу использовать query_posts для вывода только тех записей, которые были опубликованы в 2011 году и находятся в категории reports.
Вот мой код правил перезаписи...
function filter_category_by_year_rewrite_rules( $wp_rewrite ) {
/* Создает правила перезаписи для фильтрации архивов категорий по году (/category/reports/2011/)*/
$new_rules = array(
"category/(.+?)/(\d\d\d\d)/?$" => "index.php?category_name=" . $wp_rewrite->preg_index(1) . "&year=" . $wp_rewrite->preg_index(2)
);
$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
var_dump($wp_rewrite);
}
add_action('generate_rewrite_rules', 'filter_category_by_year_rewrite_rules');
Моя проблема в том, что WordPress автоматически перенаправляет index.php?category_name=reports&year=2011
на /category/reports/
без каких-либо следов параметра года. Как я могу перехватить это перенаправление?
Я пытался использовать хук template_redirect
, но безрезультатно :(
function testing_redirect() {
global $wp;
if($wp->request['matched_rule'] == 'category/(.+?)/(\d\d\d\d)/?$') {
load_template( 'category.php' ); //TEMPLATEPATH .'/category.php';
}
}
add_action('template_redirect', 'testing_redirect', 1);

Это должно работать:
add_action( 'init', 'wpa12742_init' );
function wpa12742_init(){
add_rewrite_rule( 'category/(.+?)/(\d{4})/?$', 'index.php?category_name=$matches[1]&year=$matches[2]', 'top' );
add_rewrite_rule( 'category/(.+?)/(\d{4})/page/(\d+)/?$', 'index.php?category_name=$matches[1]&year=$matches[2]&paged=$matches[3]', 'top' );
}
РЕДАКТИРОВАНИЕ
Если подумать, этого недостаточно, так как вы столкнётесь с redirect_canonical()
.
Добавьте также это:
add_filter( 'term_link', 'wpa12743_term_link', 10, 3 );
function wpa12743_term_link( $link, $term, $taxonomy ){
if('category' != $taxonomy && !preg_match( '@^\d{4}$@', get_query_var('year') ) )
return $link;
return trailingslashit( $link ) . get_query_var( 'year' );
}

Вы правы, проблема была в canonical_redirect. Смотрите мой ответ ниже, где я объяснил, как решил эту проблему. Вы имели в виду фильтровать term_link
, а не redirect_canonical
? Мне ваш способ с завершающим слэшем даже больше нравится.

Ах вот он, виновник — redirect_canonical
. Вот как я вычислил этого жучка...
function kill_canonical_redirect($redirect_url, $requested_url) {
global $wp;
if($wp->matched_rule == 'category/(.+?)/(\d\d\d\d)/?$') {
return false;
} else {
return $redirect_url;
}
}
add_filter('redirect_canonical', 'kill_canonical_redirect', 10, 2);
По сути, я проверяю правило перезаписи, которое совпало с запросом страницы, и если это то самое правило, которое я написал, то я могу отменить канонический редирект, просто вернув false.
Возможно, более полезная информация для тех, кто это читает — как я это выяснил. Я установил плагин Better HTTP Redirects (http://hakre.wordpress.com/2011/03/20/how-to-debug-redirect-problems-in-wordpress/), который предоставляет удобный инструмент для отладки редиректов при включенном WP_DEBUG
в файле wp-config.php
.
Затем я понял, что редирект срабатывает из строки 367 файла /wp-includes/canonical.php
. Посмотрев исходный код в Trac (http://core.trac.wordpress.org/browser/trunk/wp-includes/canonical.php#L367), я разобрался, как отключить канонический редирект.

Очень крутой инструмент для изучения ядра WordPress - PHPXref: http://phpxref.ftwr.co.uk/wordpress/nav.html
