WordPress как на ладони
wordpress jino

add_rewrite_rule() WP 2.1.0

Добавляет дополнительное правило перезаписи URL (ЧПУ) в структуру правил WordPress. Создает новое правило.

В WP есть белый список параметров запроса, чтобы пользователи не могли добавлять в параметры свои переменные, просто прописав их в УРЛ.

Если в правило ЧПУ добавляется новый параметр запроса, то чтобы его можно было получить с помощью get_query_var(), нужно добавить этот новый параметр в белый список. Это можно сделать с помощью add_rewrite_tag(), которая "говорит" WordPress что появились новые параметры запроса.

Или можно воспользоваться фильтром 'query_vars':

add_filter( 'query_vars', function( $vars ){
	$vars[] = 'my_var';
	return $vars;
} );

Добавление с помощью 'query_vars' - работает быстрее, т.к. не добавляются теги перезаписи в глобальную $wp_rewrite, как это происходит с add_rewrite_tag().

Функцию нужно вызывать во время или до события init.

Работает на основе: WP_Rewrite::add_rule()

Хуков нет.

Возвращает

Ничего не возвращает.

Использование

add_rewrite_rule( $regex, $query, $after );
$regex(строка) (обязательный)
Регулярное выражение, которому должна соответствовать ссылка (УРЛ). В регулярке можно использовать одну или несколько групп (()).
По умолчанию: нет
$query(строка/array) (обязательный)
Соответствующие регулярке параметры запроса. Можно использовать массив $matches[], чтобы получить значения групп регулярки.
С версии 4.4. поддерживает массив.
По умолчанию: нет
$after(строка)
Приоритет проверки. Может быть top и bottom. top - значит это правило будет проверяться первым.
По умолчанию: 'bottom'

Примеры

#1. ЧПУ для страницы

Мы создаем страницу "питание" (nutrition, ID=12) для отображения на ней различной информации о питании. Далее, эта страница использует отдельный шаблон. На страницу передаются переменные запроса food и variety.

Сделаем вместо некрасивых УРЛ: /nutrition?food=kasha&variety=manka, красивые: /nutrition/kasha/manka.

add_action('init', 'do_rewrite');
function do_rewrite(){
	// Правило перезаписи
	add_rewrite_rule( '^nutrition/([^/]*)/([^/]*)/?', 'index.php?p=12&food=$matches[1]&variety=$matches[2]', 'top' );

	// скажем WP, что есть новые параметры запроса
	add_filter( 'query_vars', function( $vars ){
		$vars[] = 'food';
		$vars[] = 'variety';
		return $vars;
	} );
}

Теперь нужно обновить правила перезаписи, для этого зайдите в настройки ЧПУ и просто обновите настройки - правила обновятся в опциях ВП.

Получить параметры в коде страницы можно через функцию get_query_var(). Например, ссылка: /nutrition/sup/risoviy

echo get_query_var('food'); // > sup
echo get_query_var('variety'); // > risoviy

При использовании $matches[], ключи массива начинаются с 1, а не 0. Как и положено в регулярных выражениях.

По умолчанию WordPress не распознает новые переменные запроса, используемые для перезаписи. Для этого нужно их зарегистрировать при помощи функции add_rewrite_tag(), если этого не сделать, правило перезаписи работать не будет.

Чтобы правило начало работать, нужно обновить (сбросить) правила в БД. Для этого нужно вызвать функцию flush_rules(). Или зайдти в Настройки -> Постоянные ссылки и просто сохраните настройки - сработает flush_rules().

#2. ЧПУ для страницы (пример 2)

Еще один пример создания ЧПУ для постоянной страницы. Сначала код:

/* Правило перезаписи для страницы sitemap
------------------------------------------------------------ */
add_action('init', 'rewrite_rule_my');
function rewrite_rule_my(){
	add_rewrite_tag('%pagetype%', '([^&]+)');
	add_rewrite_rule('^(sitemap)/([^/]*)/?', 'index.php?pagename=$matches[1]&pagetype=$matches[2]', 'top');
}

Тут мы создавали ЧПУ для постоянной страницы /sitemap?pagename=value (pagename - переменная запроса). После размещения этого кода в functions.php, начнет работать ЧПУ вида: /sitemap/value и в PHP на этой странице, можно будет использовать переменную $wp_query->query_vars['pagetype'], которая будет содержать в себе значение value. Или значение можно получить так: get_query_var('pagetype').

#3. Дружелюбная ссылка входа

Это просто пример, не имеющий никакой практической пользы. C версии 3.0 WordPress автоматически перенаправляет на /wp-login.php, если мы пытаемся зайти на /login, но так было не всегда.

Пример того, как можно сделать ссылку на страницу входа более дружелюбной, т.е. сделать так, что если мы напишем в строку браузера http://site.ru/login нас перекинет на страницу входа http://site.ru/wp-login.php:

## редирект с /login на /wp-login.php
add_action('init', 'wp_pretty_login');
function wp_pretty_login() {
	add_rewrite_rule( 'login$', 'wp-login.php', 'top' );
}

#4 ЧПУ для дочерней страницы

В параметр pagename нужно передать всю связь, а не только ярлык (slug) страницы. Допустим УРЛ нашей дочерней страницы: /parent/slug, тогда:

add_rewrite_rule( '^(parent/slug)/([^/]*)', 'index.php?pagename=$matches[1]&foo=$matches[2]', 'top' );

Т.е. в регулярном выражении нужно писать (parent/slug) а не parent/(slug)

Теперь WP начнет понимать УРЛ вида /parent/slug/value, где value будет доступна через get_query_var('foo');.

Заметки

Маленький и очень удобный плагин для просмотра всех имеющихся правил ЧПУ: Rewrite Rules Inspector

Код add rewrite rule: wp-includes/rewrite.php WP 4.8.2

<?php
function add_rewrite_rule( $regex, $query, $after = 'bottom' ) {
	global $wp_rewrite;

	$wp_rewrite->add_rule( $regex, $query, $after );
}

Cвязанные функции

Из метки: Rewrite (ЧПУ перезапись)

add_rewrite_rule 11 комментариев
Полезные 2 Вопросы 2 Все
  • Иван cайт: cw78097-wordpress-2.tw1.ru/comment

    здравствуйте, подскажите почему-то не работает

    add_action('init', 'rewrite_rule_my');
    function rewrite_rule_my(){
    	add_rewrite_tag('%pagetype%', '([^&]+)');
    	add_rewrite_rule('^(sitemap)/([^/]*)/?', 'index.php?pagename=$matches[1]&pagetype=$matches[2]', 'top');
    }

    Использую его http://cw78097-wordpress-2.tw1.ru/comment/
    З.Ы. ?otziv_id=1 вставляю через плагин, может в этом дело...

    Ответить2.8 года назад #
    • Иван cайт: cw78097-wordpress-2.tw1.ru/comment

      Решил через .htaccess

      RewriteRule ^comment/([0-9]+)/? index.php?otziv_id=$1 [L]

      а вставляю как comment/1

      Ответить2.8 года назад #
  • Здравствуйте.
    Можно ли сделать такую структуру?

    Для постов http://site.com/%post_tag%/%postname%/

    Для категорий http://site.com/%post_tag%/%category%/ (тут как бы фильтрация постов по категории и метке)

    дело в том, что в настрйках постоянных ссылок %post_tag% не работает

    Ответить2.3 года назад #
    • Kama4464

      Сделать то можно, только в этом случае нужно будет посту указать метку по умолчанию... Там не все так просто...

      1
      Ответить2.3 года назад #
  • Денис @

    Пожалуйста, подскажите кто знает:

    у меня есть правило

    add_rewrite_rule('category/([^/]*)/([^/]*)/?$', 'index.php?cat=$matches[1]&p=$matches[2]', 'top');

    Следовательно ссылки выглядят как
    site.ru/category/news/15787/
    где 15787 - айди статьи. А мне нужно чтобы вместо айди был slug статьи.
    Как нужно изменить запрос?

    Спасибо

    1
    Ответить1.4 года назад #
    • Денис @

      Кто ищет тот всегда найдет smile
      Вместо &p=$matches[2] нужно указать &name=$matches[2]

      1
      Ответить1.4 года назад #
  • Юра

    Как из этого (страница автора) site.ru/author/pupkin-vsya сделать так site.ru/pupkin-vsya.

    где pupkin-vsya - может быть кто угодно... это имя автора

    • Kama4464

      А чем тогда ссылка постоянной страницы site.ru/o-nas будет отличаться по структуре от ссылки автора site.ru/vasya? Это я к тому что это не просто и лучше не надо, а то придется всех авторов запихнуть в правила перезаписи...

  • Антон

    Помогите пожалуйста перезаписать URL.

    Есть страница с URL http://www.site.ru/?sfid=40126&_sft_brand=doc
    Как перезаписать выдаваемый URL http://www.site.ru/?sfid=40126&_sft_brand=doc на вид http://www.site.ru/brand/doc

    Ответить2 месяца назад #
  • Александр @

    Здравствуйте, я делаю по мануалу, код работает и ссылка меняется как мне нужно и преобретает вид Permalink: https://wpdev.resilienceacademy.com/worksheet-topic/2518/... Но есть один момент, на всех встроеных пост-типах есть кнопка Edit, которая позволяет отредактировать url , точнее его окончание. У меня этой кнопки нет sad в чём может быть причина? заранее благодарен!

    register_post_type('worksheet_topic', array(
    		...,
    		'rewrite' => array('slug' => 'worksheet-topic', 'with_front' => false),
    		...
    	) );
    
    add_action('init', function(){
    	$post_type = 'worksheet_topic';
    
    	add_rewrite_tag( "%worksheet_topic_id%", '([^/]+)' );
    	add_rewrite_rule('worksheet-topic/([0-9]+)?$', 'index.php?post_type='.$post_type.'&p=$matches[1]', 'top');
    
    	$permastruct = "worksheet-topic/%worksheet_topic_id%"; // наша структура ЧПУ
    
    	$args = array(
    		'with_front'  => false,
    		'ep_mask'     => EP_NONE,
    		'paged'       => false,
    		'feed'        => false,
    		'forcomments' => false,
    		'walk_dirs'   => true,
    		'endpoints'   => false,
    	);
    
    	add_permastruct( $post_type, $permastruct, $args );
    });
    
    add_filter('post_type_link', 'my_custom_permalink', 10, 3);
    function my_custom_permalink($post_link, $id = 0, $leavename) {
    	$post = &get_post($id);
    	if ( is_wp_error($post) || $post->post_type != 'worksheet_topic' ) {
    		return $post_link;
    	}
    
    	return str_replace('%worksheet_topic_id%', $post->ID, $post_link);
    }
    Ответить2 месяца назад #
  • Максим

    Привет, лучшее тут

    Ответитьмесяц назад #

Здравствуйте, !

Ваш комментарий