Кому как конечно, но я считаю, что это одна из самых непростых тем в WordPress. Я могу просто описать, что класс WP_Rewrite нужен для того-то, у него есть такие-то методы и свойства и привести пару примеров — всё, как в официальной документации 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
содержит в себе всю необходимую информацию о структуре URL в WordPress. О его методах и свойствах будет написано чуть ниже.$post_type = 'page'
в данном примере это тип постов — страницы.Как я уже говорил, мы разбираться с WP_Rewrite мы будем поэтапно, и сейчас мы поглядим на его свойства.
/%postname%/
.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);
[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% // ярлык записи произвольного типа )
rewritecode
и приведу пример — возьмем rewritecode[0]
— это год, значением может быть четырехзначное число, и правило для года rewritereplace[0]
будет соответствующим ([0-9]{4})
.rewritecode
, например для года year=
.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);
/author/%author%
), архивов по дате (/%year%/%monthnum%/%day%
, но может быть в другом порядке, в зависимости от настроек постоянных ссылок), страниц (%pagename%
), фида комментария (comments/feed/%feed%
), поиска (%search%
).
Зависит от предыдущего параметра (base).
index.php
./blog/
:
$rewrite_rules = get_option( 'rewrite_rules' );
.
Сам этот массив выглядит примерно следующим образом (я заскринил только верхнюю его часть, так как он довольно большой).
Прямо в него можно добавлять и свои правила.
.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]
http://адрес-сайта/dir1/параметр
, то, содержимым страницы будет http://адрес-сайта/dir1.php?param=параметр
, при этом сам URL не изменится.За последнюю неделю или две очень многие люди связывались со мной (через сайт / через комментарии / и в вк) и спрашивали, как удалить префикс типа записи из URL, то есть сделать так, чтобы URL имели следующий вид http://адрес-сайта/ярлык-типа-записи
.
Не знаю, с чего вдруг так резко это всем понадобилось, но буду рад помочь. Но имейте ввиду две вещи:
Для начала, во время непосредственно регистрации типа функцией register_post_type() рекомендую указать параметр rewrite
равным false
.
Затем в код сайта отправляется следующее:
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');
После добавления этого кода не забудьте зайти в настройки постоянных ссылок и сохранить изменения.
После установки кода из предыдущего примера у вас вряд ли что-то заработает — при переходе на страницу товара мы будем получать ошибку 404, якобы товар не найден.
Исправляется на самом деле легко:
function true_rewrite_conflicts( $request ) { if(!is_admin()) $request['post_type'] = array('product', 'post', 'page'); // перечисляем типы записей с подобной структурой пермалинков return $request; } add_filter( 'request', 'true_rewrite_conflicts' )
Как я уже писал выше, в этом посту подразумевается, что у вас уже есть базовые знания о классах, объектах, их методах и свойствах.
true
, если на сайте включены постоянные ссылки, false
— если не включены (то есть URL имеют вид ?p=14748.%pagename%
./%year%/%monthnum%/%day%
./category/%category%
./author/%author%
.$wp_rewrite->rewrite_rules
, сохраняет их в базу данных.$tag
в массив $wp_rewrite->rewritecode
, $pattern
— в $wp_rewrite->rewritereplace
и $query
в $wp_rewrite->queryreplace
. Подробнее про каждый из этих массивов написано выше, в свойствах класса.$name
— это название структуры, $struct
— собственно структура..htaccess
в виде строки.На самом деле про метод WP_Rewrite можно написать ешё столько же (и даже больше), но пожалуй я лучше разобью информацию на отдельные статьи. Если у вас есть вопросы или дополнения к посту — пожалуйста оставляйте их в комментариях.
Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.
Здравствуйте, на счет префикса всё отлично работает, надо еще потестировать
Но я использовал не много другой подход, вместо первой функции я при регистрации нового типа поста указал 'rewrite' => array( 'slug' => '/')
И так и так всё работает
Спасибо огромное
Классно. Пытаюсь сделать функцию для окончания .html, но только для конечных страниц, пока не получается. То есть сделать проверку, если у страницы есть дочерние страницы, то урл не менять и оставить слеш на конце, а если дочерних нет, то сделать .html
Пример:
site.ru/about/
site.ru/about/team.html
Вот такого пытаюсь добиться...
Может есть идеи или готовые решения?
Думаю вам нужно взять за основу первый пример, определить там глобально $wp_query, через неё узнать ID страницы и есть ли у неё дочерние, если дочерних нет, то подставляем .html.
Спасибо. А еще проблема возникла...
Делаю полностью как в первом примере. А постоянные ссылки для записей задаю как /%category%/%postname%.html и выдает 404 ошибку у страниц блога.
Видимо это из-за проверки на html?
Можно подробнее, какие страницы в 404?
Все круто , но нужно написать что после использования таких сниппетов нужно на странице настроек постоянных ссылок нажимать кнопку сохранить дабы .htaccess перегенерился и
,использовать с умом ( не при каждом вызове )
так как он несет лишние накладные расходы
Михаил подскажи пожалуйста, заметил на постраничной навигации вот такого вида ссылки
из-за таких ссылок появляются дубли страниц.
В
header.php
их нет?Нет, Михаил в header их нет. Я уже всё перерыл, то есть сейчас у меня получается есть страницы с ссылками
и есть страницы
В google.ru/webmaster мне эти ссылки уже показывает, что одинаковые мета описание.
Вот такие блин дела. Выручай Михаил.
А, да, поставь просто 301-й редирект с первых на вторые. А лучше на всех их просто добавить:
Здравствуйте.
Можно ли сделать такую структуру?
Для постов http://site.com/%post_tag%/%postname%/
Для категорий http://site.com/%post_tag%/%category%/ (тут как бы фильтрация постов по категории и метке)
дело в том, что в настрйках постоянных ссылок %post_tag% не работает
Добрый день!
А вы попробуйте сначала осуществить подобное с отключенными пермалинками, то есть обычными URL с параметрами. Если получится, значит можно.
Спасибо.
Вот вчера попробовал через этот код сделать
/%post_tag% не работает
А я и говорю, попробуйте вообще без пермалинков это реализовать, а когда получится, уже добавьте правила.
Михаил спасибо. Хотел ещё у тебя спросить, посмотрел код твоей страницы, скажи как вывести без плагина all_in_one_seo_pack , keywords и description?
Можно вот так или же просто через произвольные поля.
Добрый день
Михаил подскажи. У меня установлен e-commerce, интернет магазин жетской обуви. В продукты добавлены таксономии пол и сезонность. Мне нужно, что бы по ссылке сайт.ру/для_мальчиков/зима отображалась обувь для мальчиков на зиму. Причем по ссылке сайт.ру/index.php?пол=для_мальчиков&сезон=зима продукция все верно фильтруется. В постоянных ссылках прописано /%pagename%/
Если в Постоянных ссылках прописываю /%пол%/%сезон%/ то сайт работает как нужно, но перестают работать обычные статьи, перекидывает на 404 страницу
Добрый день!
Посмотрите внимательнее пример с $wp_rewrite->non_wp_rules, думаю в данном случае он должен вам помочь.
Михаил, спасибо!
Сделал так:
Позвольте добавить ссылку, не в качестве рекламы, но еще одна статья по этой же теме, которая мне помогла разобраться.
http://omurashov.ru/wordpress_rewrite_rules/
я пробовал делать по Вашей статье с использование add_rewrite_rule, нечего не работает, мб методы уже устарели или хз, с низу коммент с моей проблемой, почитай плз мб поможете)
Здравствуйте, у меня такая проблема, пишу плагин который берет инфу не с WP, а по API с сервера, получаются вот такие ссылки mysite.ru/athletics/?sport=baseball&id=2, нужно сделать ссылки такого вида mysite.ru/athletics/baseball/2, с прочитанного выше, понял только как сделать через запись в .htaccess но такой вариант не подходит. Помогите пожалуйста с решением.
Здравствуйте!
А посмотрите предыдущие комментарии, там уже была рассмотрена подобная проблема.
Михаил, добрый день!
Помогите пожалуйста как изменить такой линк:
на такой:
То есть убрать слово «date».
И (это уже второй вопрос), поменять его на слово «архив_сайта» или любое другое.
С Уважением, ваш постоянный читатель!
Уже разобрался сам.
Чтобы не отвлекать маэстро глупостями, напишу для задающихся тем-же вопросом сразу готовый код:
На этой странице всё подробно описано:
Когда-нибудь её переведут на Русский язык и вообще всё будет замечательно.
Всем Good bye, Au revoir, Auf Wiedersehen, Arrivederci, Hasta la vista, ну, или просто, Пока!
Добрый день!
Рад, что разобрались :)
Здравствуйте, помогите пожалуйста с проблемой.
Нужно чтобы метка открывалась как поддомен, например site.ru?tag=dom было доступно по адресу dom.site.ru
сервер для работы с поддоменами настроен.
Вот почему то если брать слаг метки из урл и передавать его в переменную $categorystr, то ничего не работает.
$categorystr = $domain[0]; //в таком виде ошибка 404
хотя если я сам укажу к переменной слаг метки вот так:
$categorystr = 'dom'; то все работает.
Подскажите, в чем может быть проблема?
Здравствуйте! Попробуйте:
Спасибо. к сожалению так тоже не работает.
Почему то работаю только переменные $matches[1] которые берут данные из регулярки,
так например:
$rules["cat/?([a-z0-9_\-\.]+)$"] = "index.php?cat=$matches[1]" ;
Может можно как-то сюда поддомен запихать:
$rules["http://dom.site.ru/cat/?([a-z0-9_\-\.]+)$"] = "index.php?cat=$matches[1]" ; ?
Здравствуйте! Подскажите, есть задача, чтобы страницы, у которых в урл добавляется несколько слешей, отдавали код ответа 404 (например, страницы типа www.site.ru////cat/post). Вордпресс просто переписывает все слеши, страницы отдают 200 ОК. В каком конкретно месте он их удаляет, чтобы можно было его остановить?
Заранее спасибо
Михаил, здравствуйте!
Как изменять сам slug названия рубрик под свой формат? Например:
было http://site.ru/система стало http://site.ru/Система (с большой буквы)
или
было http://site.ru/windows-7 стало http://site.ru/Windows_7 (С большой буквы и нижнее подчёркивание)
Рубрик не так много и можно для всех прописать изменение slug'а.
Заранее признателен за помощь!
миша подскажите, а как добавить расширение .html для категорий?
Данный код не работает для категории
Приветствую, Михаил! Я насчет удаления слага в пермалинках кастомных постов.
Баги действительно вылезают.
Перестают работать статика и шаблоны страниц. Например, у меня задана (через штатные настройки) статическая страница и страница блога, после изменения удаления слага на главной выводятся записи, причем вперемешку и штатные и произвольные, а страница блога стала просто страницей. Как сие полечить?
Михаил, привет!
А не подскажешь как лучше поступить в случае, когда нужно поменять у всех внутренних ссылок на странице/посте сайта - доменное имя? Например, у меня сайт на https://stename.ru и мне нужно, чтобы все ссылки у которых в качестве домена указан текущий ( https://stename.ru/url ) на выводимой странице/посте были заменены на https://stename.info/url .
Я придумал, как это реализовать с помощью JS, но никак не могу сообразить, как это осуществить с помощью WP.
Привет,
приходит на ум фильтр
the_content
иstr_replace()
.Спасибо!
Но я так понимаю, вылавливать ссылки из навигации, сайдбаров и футера придется отдельно.
yez
Привет! Отличный сайт) реально нахожу то что нужно. Продолжайте его наполнять! Простенький сайт сам сделаю на WP. А есть еще сложный проект это закажу у Миши
Привет! Очень рад! 😊
Доброго дня. Подскажите пожалуйста, у меня все ссылки на сайте вида: http://site.ru/spb/product/product_name
http://site.ru/msk/product/product_name
Но при переходе по ним, выдает ошибку 404. Подскажите, как можно сделать что бы движок обрабатывал ссылки с регионом.