Как изменить URL конкретных страниц / записей / рубрик / меток / таксономий через functions.php

Если вы читаете эту статью, то наверняка хотя бы раз слышали про WP_Rewrite. Этот класс позволяет работать с постоянными ссылками в WordPress, изменять их вид и структуру. WP_Rewrite задает правила перезаписи, которые будут действовать по всему блогу.

Сейчас же я покажу вам очень простой но действенный метод ручной замены URL конкретных страниц сайта на WordPress. Состоит он всего из трёх шагов: редиректа старых страниц на новые, изменения запроса к базе, перезаписи ссылок.

Шаг 1. Редиректы через хук template_redirect

Этот шаг нужен для того, чтобы страница не была доступна по двум URL одновременно, поэтому мы ставим 301й редирект со всех старых URL на новые (желающие могут реализовать это также через .htaccess).

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

Весь код, который вы увидите в этой статье — в functions.php.

function true_301_redirect() {
	/* в массиве указываем все старые=>новые ссылки  */
	$rules = array(
		array('old'=>'/category/без_рубрики/','new'=>'/category/Без_рубрики/'), // рубрика
		array('old'=>'/контакты/','new'=>'/Контакты/'), // страница
		array('old'=>'/привет-мир/','new'=>'/хеллоу-мир/'), // запись
		array('old'=>'/tag/метка/','new'=>'/tag/Метка/') // метка
	);
	foreach( $rules as $rule ) :
		// если URL совпадает с одним из указанных в массиве, то редиректим
		if( urldecode($_SERVER['REQUEST_URI']) == $rule['old'] ) :
			wp_redirect( site_url( $rule['new'] ), 301 );
			exit();
		endif;
	endforeach;
}
 
add_action('template_redirect', 'true_301_redirect');

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

Ссылки на описания функций, использованных в примерах, вы найдёте в конце статьи.

Шаг 2. Изменение параметров запроса через хук request

Окей, редиректы проставили и, если вы уже начали пробовать то, что получилось, то у вас наверняка повылазили ошибки 404. Сейчас нам нужно добиться того, чтобы новые URL WordPress воспринимал как старые.

function true_request( $query ){
 
	$url_zapros = urldecode($_SERVER['REQUEST_URI']);
 
	/* для рубрик */
	if( $url_zapros == '/category/Без_рубрики/' )
		$query['category_name'] = 'без_рубрики';
 
	/* для страниц */
	if( $url_zapros == '/Контакты/' ){
		$query['pagename'] = urlencode('контакты');
		unset($query['name']);
	}
 
	/* для записей */
	if( $url_zapros == '/хеллоу-мир/' )
		$query['name'] = 'привет-мир';
 
	/* для меток */
	if( $url_zapros == '/tag/Метка/' )
		$query['tag'] = 'метка';
 
	return $query;
}
 
add_filter( 'request', 'true_request', 9999, 1 );

Шаг 3. И конечно же сама перезапись ссылок

Хуки для записей и страниц будут отличаться от хуков для рубрик и меток.

Для записей / страниц

function true_posts_links( $url, $post ){
	if( !is_object( $post ) )
		$post = get_post( $post_id );
 
	$replace = $post->post_name;
 
	/* замены для записей и страниц,
		к сожалению тут только по ID замену можно сделать */
 
	if( $post->ID == 1 ) 
		$replace = 'хеллоу-мир';
	if( $post->ID == 12 ) 
		$replace = 'Контакты';
 
	$url = str_replace($post->post_name, $replace, $url );
	return $url;
}
 
add_filter( 'post_link', 'true_posts_links', 'edit_files', 2 );
add_filter( 'page_link', 'true_posts_links', 'edit_files', 2 );
add_filter( 'post_type_link', 'true_posts_links', 'edit_files', 2 );

Обязательно ли делать проверку именно по ID записи? Да, если в URL присутствует кириллица. Если вы не знаете, где найти ID, спрашивайте в комментах, всё расскажу и покажу.

Перезапись ссылок для рубрик / меток

function true_term_links( $url, $term, $taxonomy ){
	$replace = $term->slug;
 
	/* замены для рубрик/меток, опять-таки нужно указать ID и желаемый ярлык */
	if( $term->term_id == 5 ) 
		$replace = 'Без_рубрики';
	if( $term->term_id == 55 ) 
		$replace = 'Метка';
 
	$url = str_replace($term->slug, $replace, $url );
 
	return $url;
}
 
add_filter( 'term_link', 'true_term_links', 10, 3 );

Альтернатива всему этому в виде плагина Custom Permalinks

Если вы не хотите мудохаться через functions.php, то рекомендую плагин Custom Permalinks. Мне он показался очень удобным — прямо в админке можно указать свои произвольные урлы.

Например при создании рубрик:

Произвольный URL рубрики при помощи плагина Custom Permalinks

Миша

В последние годы я долго не знал, что мне делать с сайтом misha.blog, ведь он практически не приносит никакого профита, но недавно я осознал, что моя миссия – способствовать распространению WordPress. Ведь WordPress – это лучший движок для разработки сайтов – как для тех, кто готов использовать заложенную структуру этой CMS, так и для тех, кто предпочитает headless решения.

Сам же я впервые познакомился с WordPress в 2009 году. Организатор WordCamp. Преподаватель в школах Epic Skills и LoftSchool.

Если вам нужна помощь с вашим сайтом или может даже разработка с нуля на WordPress / WooCommerce — пишите. Я и моя команда сделаем вам всё на лучшем уровне.

Комментарии — 15

  • Александр 25 декабря 2015 #

    Привет -) Мне кажется, такие штуки не очень актуальны, хотя мы недавно с джумлы перевозили сайт - что-то похожее делали.

    Но есть актуальные проблемы, которые даже не гугляться.
    Например, пример загрузки лого через кастомайзер - http://kwight.ca/2012/12/02/adding-a-logo-uploader-to-your-wordpress-site-with-the-theme-customizer/.
    Но как эту фигню реализовать с поддержкой экранов ретина? Все реализации, которые встречались и я использую - просто поля для загрузки двух лого на странице настроек темы. Но хочется ведь красиво -)

    • Миша 25 декабря 2015 #

      Привет, ну чтобы не было двух лого, нужно в формате svg загружать, или вы хотите чтобы загружалась большая картинка и WP её автоматически подрезал два ретины и для обычного?

      • Александр 25 декабря 2015 #

        Второй вариант более дружелюбный -)

        • Миша 25 декабря 2015 #

          В общем эти стили просто лепим к лого и всё — самый просто вариант.

          max-width: сколько_надо; height: auto;
          • Александр 25 декабря 2015 #

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

  • Максим 26 декабря 2015 #

    Привет.

    А как можно автоматически перезаписать ссылки, исходя из новых правил, прописанных через add_rewrite_rule? К примеру, я поставил новые правила, по ним записи/категории открываются, но по умолчанию в цикле всё равно выводятся первоначальные. Как сделать, чтобы они полностью перезаписались, причём не конкретные посты, а все пути к постам или категориям и пользовательским таксономиям. Из плагина "Custom Post Type Permalinks" выцепить не смог.

    Спасибо.

    • Миша 27 декабря 2015 #

      Привет,

      если я правильно понял вопрос, то вам нужны фильтры post_link, post_type_link, term_link.

      • Максим 27 декабря 2015 #

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

        Есть пользовательский тип записей и есть пользовательские таксономии, к примеру, "город" и "тип". У меня стоит задача привести ссылки на посты к виду:

        http://домен/город/тип/slug_записи

        и страницы таксономии к виду:

        http://домен/город/slug_таксономии

        Отсюда идут вопросы.
        1) Можно ли с помощью

        query_vars

        автоматически генерировать параметр в ссылке, исходя из принадлежности к таксономии (разные города, типы)? Или нужны другие инструменты?
        2) Если будет первый пункт, то правила без проблем создадутся с помощью

        add_rewrite_rule

        . При вводе в адресной строке новых ссылок мы попадём на нужные страницы. Но ссылки на записи и таксономии при выводе их в цикле не поменялись на новые. Какой конструкцией можно это поправить? В Вашем примере описывается конкретные посты/категории, их нужно задавать. Наверное, нужно как-то проходить циклом что-ли по всем существующим или правильней было бы менять на лету, исходя из поступившего запроса?

        Таких понятных справок в интернете я не нашёл, хотя это многим нужная вещь.
        Спасибо.

        • Миша 28 декабря 2015 #

          Могу ответить лишь то, что у меня сейчас серия постов идёт чисто по этой теме, просто следите за обновлениями.

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

  • Дмитрий 4 декабря 2016 #

    Миша, подскажите пожалуйста, я использую такой редирект, но он не срабатывает:

    add_action( 'template_redirect', function() {
    	if ( preg_match( '#^/author/$user_ID/?$#i', $_SERVER['REQUEST_URI'] ) ) {
    		wp_redirect( 'http://mysite.ru/404', 301 );
    		exit;
    	}
    } );

    Я не могу понять как прописать правильно $user_ID в строке редиректа.
    У меня стоит плагин и после авторизации юзеры переходят в свой профиль по ссылке http://mysite.ru/author/id юзера/
    И юзер может в строке вбить другого юзера и зайти в его профиль.
    Вот хочу убрать эту возможность через редирект.

    • Миша 4 декабря 2016 #

      Добрый вечер!
      Рекомендую получить ID пользователя через функцию get_current_user_id().

  • Maksim 15 февраля 2020 #

    Добрый день, подскажите, пожалуйста, как можно поменять пермалинк постов только определенной категории через functions.php?
    Сейчас все посты имеют /%category%/%postaname%
    Но в определенной категории мне надо вывести /%category%/%author%/%postaname%
    Спасибо

  • Залиха 24 марта 2020 #

    Добрый день! Как можно в теме Travel Tour удалить в адресной строке слово /tour, который появляется при открытий какой-либо записи созданной в данной теме? А также хотелось бы, чтобы в адресной строке появлялись фильтры и категории данной темы, например site.ru/страна/город/курорт/отель. категории на сайте нет, как я понимаю это slug темы traveltour или плагина tourmaster Пожалуйста, подскажите решение!

  • Ярослав 7 апреля 2020 #

    Как поменять url woocommerce?
    нужна структура сайт/catalog - базовый url каталога товаров
    сайт/catalog/товар - адрес конкретного товара
    если правлю в постоянных ссылках выходит ошибка, как это можно исправить?

    • Миша 9 апреля 2020 #
      1. Поменять ярлык страницы Магазин,
      2. В постоянных ссылках выбрать настройку «База магазина».

Оставить комментарий

Если вы хотите добавить код, не забудьте обернуть его в <pre lang="php"></pre>, если же код – меньше одной строчки, то можно и в <code></code>.