Кому как конечно, но я считаю, что это одна из самых непростых тем в WordPress. Я могу просто описать, что класс WP_Rewrite нужен для того-то, у него есть такие-то методы и свойства и привести пару примеров — всё, как в официальной документации WordPress. Но так я делать не стану, потому что в таком случае от статьи будет мало толку и никто в итоге так и не поймёт, как работать с этим классом.
Поэтому я начну с примеров. Думаю, что многие из этих примеров вам уже знакомы. Некоторые даже реализованы в виде плагинов.
И ещё кое-что, в посту подразумевается, что у вас есть некоторые базовые знания:
Пример 1. Как добавить .html для страниц в WordPress?
То есть страницы по умолчанию в WP не имеют никакого расширения и в настройках постоянных ссылок мы его не можем им добавить. Так как в итоге добавить для страниц .html, .htm, .pl, .phtml и так далее?
Открывайте свой functions.php
, потому что работать мы будем в основном только в нём.
function true_add_html_on_pages() { // при работе с $wp_rewrite, как и с $wpdb, в первую очередь глобально определяем класс global $wp_rewrite; // метод $wp_rewrite->get_page_permastruct() возвращает нам структуру URL страниц, по умолчанию %pagename% // функцией strpos() мы делаем проверку, не присутствует ли уже расширение .html (%pagename%.html) if ( !strpos($wp_rewrite->get_page_permastruct(), '.html')){ // если не присутствует, то добавляем его $wp_rewrite->page_structure = $wp_rewrite->page_structure . '.html'; // метод flush_rules() применяет сделанные изменения $wp_rewrite->flush_rules(); } } // вешаем на хук init add_action('init', 'true_add_html_on_pages', -1); // вроде бы всё ок, вот только WordPress добавляет слэши на конце и у нас получается %pagename%.html/ - сейчас мы это исправим function true_remove_slash_on_pages( $url, $post_type){ global $wp_rewrite; // $wp_rewrite->using_permalinks() возвращает true, если постоянные ссылки используются на сайте // $wp_rewrite->use_trailing_slashes равен true, если слэши добавляются на конце URL // нам нужно удалить слэши только с страниц, поэтому $post_type должен быть равен page if ($wp_rewrite->using_permalinks() && $wp_rewrite->use_trailing_slashes==true && $post_type == 'page'){ // удаляем слэш return untrailingslashit( $url ); } else { // возвращаем всё как есть return $url; } } // вешаем на фильтр user_trailingslashit add_filter('user_trailingslashit', 'true_remove_slash_on_pages',70,2);
А теперь подробные комментарии к этому примеру.
Свойства объекта WP_Rewrite + примеры
Как я уже говорил, мы разбираться с WP_Rewrite мы будем поэтапно, и сейчас мы поглядим на его свойства.
- $wp_rewrite->permalink_structure
- Структура URL, которая определена на странице «Настройки > Постоянные ссылки», например
/%postname%/
. - $wp_rewrite->use_trailing_slashes
- Будет ли WordPress автоматически добавлять слэши на конце ссылок. По умолчанию
true
— добавляются. Как сделать так, чтобы не добавлялись? Вы можете использовать фильтрuser_trailingslashit
из примера выше, а можете изменить значение напрямую в$wp_rewrite
:function true_no_trailingslashes() { global $wp_rewrite; $wp_rewrite->use_trailing_slashes = false; // даже не нужно обновлять правила через flush_rules() } add_action('init', 'true_no_trailingslashes', 1);
- $wp_rewrite->rewritecode
- Полный список (массив) тегов, доступных для использования в постоянных ссылках, например у меня он такой:
[rewritecode] => Array ( [0] => %year% // год [1] => %monthnum% // номер месяца [2] => %day% // число [3] => %hour% // час [4] => %minute% // минуты [5] => %second% // секунды [6] => %postname% // ярлык поста [7] => %post_id% // ID поста [8] => %author% // автор поста (его nicename/логин) [9] => %pagename% // ярлык страницы [10] => %search% // поисковой запрос [11] => %category% // ярлык категории [12] => %post_tag% // ярлык метки [13] => %post_format% // название формата поста [14] => %product% // ярлык записи произвольного типа )
- $wp_rewrite->rewritereplace
- Назову этот параметр массивом шаблонов доступных значений для каждого значения
rewritecode
и приведу пример — возьмемrewritecode[0]
— это год, значением может быть четырехзначное число, и правило для годаrewritereplace[0]
будет соответствующим([0-9]{4})
. - $wp_rewrite->queryreplace
- Массив параметров URL, соответсвующих для каждого
rewritecode
, например для годаyear=
. - $wp_rewrite->author_base, $wp_rewrite->pagination_base, $wp_rewrite->search_base, $wp_rewrite->feed_base
- Префикс URL страниц соответственно: архивов автора (по умолчанию
author
), постраничной навигации (page
), поиска (search
), фидов (feed
).То есть напрмер URL страницы архивов автора
http://адрес-сайта/author/misha/
. Мы можем легко и просто его изменить, напрмиер наwriter
:function true_writer_not_an_author() { global $wp_rewrite; $wp_rewrite->author_base = 'writer'; $wp_rewrite->flush_rules(); // лучше применяйте изменения через Настройки > Постоянные ссылки } add_action('init', 'true_writer_not_an_author', 1);
- $wp_rewrite->author_structure, $wp_rewrite->date_structure, $wp_rewrite->page_structure, $wp_rewrite->feed_structure, $wp_rewrite->comment_feed_structure, $wp_rewrite->search_structure
- Полная структура URL соответственно: страниц архивов автора (по умолчанию —
/author/%author%
), архивов по дате (/%year%/%monthnum%/%day%
, но может быть в другом порядке, в зависимости от настроек постоянных ссылок), страниц (%pagename%
), фида комментария (comments/feed/%feed%
), поиска (%search%
).Зависит от предыдущего параметра (base).
- $wp_rewrite->root
- Корень установки WordPress, добавляется ко всем структурам. По умолчанию
index.php
. - $wp_rewrite->front
- То, что находится непосредственно перед структурой постоянных ссылок, напрмиер на скриншоте это
/blog/
: - $wp_rewrite->rewrite_rules
- Все правила перезаписи URL для сайта. Значение этого параметра хранится в базе данных, его можно получить при помощи
$rewrite_rules = get_option( 'rewrite_rules' );
.Сам этот массив выглядит примерно следующим образом (я заскринил только верхнюю его часть, так как он довольно большой).
Прямо в него можно добавлять и свои правила.
- $wp_rewrite->non_wp_rules
- Ассоциативный массив правил, которые не обрабатываются самим WordPress вообще, а идут прямиком в
.htaccess
.function true_generate_rewrite_rules() { // не забываем обращаться к глобальной переменной $wp_rewrite global $wp_rewrite; // вот такой вот массив, правил в нем может быть сколько угодно, я добавил лишь два $non_wp_rules = array( 'dir1/(.*)$' => 'dir1.php?param=$1', 'dir2/(.*)$' => 'direct25.php?param=$1' ); // объелиняем те $non_wp_rules, которые уже используются с нашими $wp_rewrite->non_wp_rules = $non_wp_rules + $wp_rewrite->non_wp_rules; // не забываем про flush_rules() - либо так, но лучше через Настройки -> Постоянные ссылки //$wp_rewrite->flush_rules(); } // правильнее всего повесить функцию на специально предназначенный хук generate_rewrite_rules add_action('generate_rewrite_rules', 'true_generate_rewrite_rules');
Данный код добавит в
.htaccess
следующие строки:RewriteRule ^dir1/(.*)$ /dir1.php?param=$1 [QSA,L] RewriteRule ^dir2/(.*)$ /direct25.php?param=$1 [QSA,L]
Теперь по порядку:
- Массив
$wp_rewrite->non_wp_rules
— это правила, которые добавляются непосредственно в.htaccess
под флагом[QSA,L]
- Если на сайте мы перейдём по URL
http://адрес-сайта/dir1/параметр
, то, содержимым страницы будетhttp://адрес-сайта/dir1.php?param=параметр
, при этом сам URL не изменится.
- Массив
function true_no_trailingslashes() { global $wp_rewrite; $wp_rewrite->use_trailing_slashes = false; // даже не нужно обновлять правила через flush_rules() } add_action('init', 'true_no_trailingslashes', 1);
[rewritecode] => Array ( [0] => %year% // год [1] => %monthnum% // номер месяца [2] => %day% // число [3] => %hour% // час [4] => %minute% // минуты [5] => %second% // секунды [6] => %postname% // ярлык поста [7] => %post_id% // ID поста [8] => %author% // автор поста (его nicename/логин) [9] => %pagename% // ярлык страницы [10] => %search% // поисковой запрос [11] => %category% // ярлык категории [12] => %post_tag% // ярлык метки [13] => %post_format% // название формата поста [14] => %product% // ярлык записи произвольного типа )
То есть напрмер URL страницы архивов автора http://адрес-сайта/author/misha/
. Мы можем легко и просто его изменить, напрмиер на writer
:
function true_writer_not_an_author() { global $wp_rewrite; $wp_rewrite->author_base = 'writer'; $wp_rewrite->flush_rules(); // лучше применяйте изменения через Настройки > Постоянные ссылки } add_action('init', 'true_writer_not_an_author', 1);
Зависит от предыдущего параметра (base).
Сам этот массив выглядит примерно следующим образом (я заскринил только верхнюю его часть, так как он довольно большой).
Прямо в него можно добавлять и свои правила.
function true_generate_rewrite_rules() { // не забываем обращаться к глобальной переменной $wp_rewrite global $wp_rewrite; // вот такой вот массив, правил в нем может быть сколько угодно, я добавил лишь два $non_wp_rules = array( 'dir1/(.*)$' => 'dir1.php?param=$1', 'dir2/(.*)$' => 'direct25.php?param=$1' ); // объелиняем те $non_wp_rules, которые уже используются с нашими $wp_rewrite->non_wp_rules = $non_wp_rules + $wp_rewrite->non_wp_rules; // не забываем про flush_rules() - либо так, но лучше через Настройки -> Постоянные ссылки //$wp_rewrite->flush_rules(); } // правильнее всего повесить функцию на специально предназначенный хук generate_rewrite_rules add_action('generate_rewrite_rules', 'true_generate_rewrite_rules');
Данный код добавит в .htaccess
следующие строки:
RewriteRule ^dir1/(.*)$ /dir1.php?param=$1 [QSA,L] RewriteRule ^dir2/(.*)$ /direct25.php?param=$1 [QSA,L]
Теперь по порядку:
Пример 2. Постоянные ссылки произвольного типа записей в WordPress. Как удалить префикс типа записи из URL
За последнюю неделю или две очень многие люди связывались со мной (через сайт / через комментарии / и в вк) и спрашивали, как удалить префикс типа записи из URL, то есть сделать так, чтобы URL имели следующий вид http://адрес-сайта/ярлык-типа-записи
.
Не знаю, с чего вдруг так резко это всем понадобилось, но буду рад помочь. Но имейте ввиду две вещи:
Шаг 1. Изменяем параметр rewrite регистрируемого типа записей
Для начала, во время непосредственно регистрации типа функцией register_post_type() рекомендую указать параметр rewrite
равным false
.
Шаг 2. Настраиваем структуру постоянных ссылок данного типа записей
Затем в код сайта отправляется следующее:
function true_post_type_rewrite() { global $wp_rewrite; // в данном случае мой тип записей был - Товары (product) // этот код позволит перезаписать урлы // параметры add_rewrite_tag('%название_тега%', '%маска_символов%', '%url_параметр%') $wp_rewrite->add_rewrite_tag("%product%", '([^/]+)', "product="); $wp_rewrite->add_permastruct('product', '%product%' ); } add_action( 'init', 'true_post_type_rewrite');
После добавления этого кода не забудьте зайти в настройки постоянных ссылок и сохранить изменения.
Шаг 3. Исправляем ошибку 404
После установки кода из предыдущего примера у вас вряд ли что-то заработает — при переходе на страницу товара мы будем получать ошибку 404, якобы товар не найден.
Исправляется на самом деле легко:
function true_rewrite_conflicts( $request ) { if(!is_admin()) $request['post_type'] = array('product', 'post', 'page'); // перечисляем типы записей с подобной структурой пермалинков return $request; } add_filter( 'request', 'true_rewrite_conflicts' )
Методы объекта WP_Rewrite
Как я уже писал выше, в этом посту подразумевается, что у вас уже есть базовые знания о классах, объектах, их методах и свойствах.
- $wp_rewrite->using_permalinks()
- Возвращает
true
, если на сайте включены постоянные ссылки,false
— если не включены (то есть URL имеют вид ?p=14748. - $wp_rewrite->get_page_permastruct()
- Возвращает структуру постоянных ссылок для страниц, по умолчанию
%pagename%
. - $wp_rewrite->get_date_permastruct()
- Возвращает структуру постоянных ссылок для архивов по дате, по умолчанию
/%year%/%monthnum%/%day%
. - $wp_rewrite->get_category_permastruct()
- Возвращает структуру постоянных ссылок для рубрик, по умолчанию
/category/%category%
. - $wp_rewrite->get_author_permastruct()
- Возвращает структуру постоянных ссылок для страниц архивов автора, по умолчанию
/author/%author%
. - $wp_rewrite->flush_rules()
- Применяет новые значения массива
$wp_rewrite->rewrite_rules
, сохраняет их в базу данных. - $wp_rewrite->add_rewrite_tag( $tag, $pattern, $query )
- Функция добавляет переменную
$tag
в массив$wp_rewrite->rewritecode
,$pattern
— в$wp_rewrite->rewritereplace
и$query
в$wp_rewrite->queryreplace
. Подробнее про каждый из этих массивов написано выше, в свойствах класса. - $wp_rewrite->add_permastruct( $name, $struct )
- Позволяет добавить структуру постоянных ссылок, где
$name
— это название структуры,$struct
— собственно структура. - $wp_rewrite->mod_rewrite_rules()
- Возвращает список правил для
.htaccess
в виде строки. - $wp_rewrite->set_permalink_structure()
- Про этот метод на моем блоге есть отдельный пост.
На самом деле про метод WP_Rewrite можно написать ешё столько же (и даже больше), но пожалуй я лучше разобью информацию на отдельные статьи. Если у вас есть вопросы или дополнения к посту — пожалуйста оставляйте их в комментариях.