add_rewrite_rule()
Добавляет новое правило перезаписи URL (ЧПУ) в структуру правил WordPress.
Если в правило ЧПУ добавляется новый параметр запроса, то чтобы его можно было получить с помощью get_query_var(), нужно добавить этот новый параметр в белый список с помощью функции add_rewrite_tag(), которая "говорит" WordPress что появились новые параметры запроса. В WP есть белый список параметров запроса, чтобы пользователи не могли добавлять в параметры любые переменные, просто прописав их в УРЛ.
Или можно воспользоваться фильтром query_vars. В отличии от add_rewrite_tag() в этом случае не добавляются теги перезаписи в глобальный объект $wp_rewrite:
add_filter( 'query_vars', function( $vars ){
$vars[] = 'my_var';
return $vars;
} );
Функцию нужно вызывать во время или до события init.
При добавлении нескольких правил обратите внимание, что (начиная с версии 4.9.8) правила применяются в порядке добавления, независимо от того, находятся ли они вверху или внизу. Например:
add_rewrite_rule( '^book/(.*)', 'index.php?pagename=foo&book=$matches[1]', 'top' ); add_rewrite_rule( '^book/mammals/(.*)', 'index.php?pagename=foo&bookmam=$matches[1]', 'top' );
Второе правило никогда не сработает, потому что всегда будет срабатывать первое правило до обработки второго.
Смотрите список занятых названий для переменных запроса.
Rewrite Rules Inspector — небольшой плагин для просмотра всех имеющихся правил ЧПУ.
Хуков нет.
Возвращает
null. Ничего не возвращает.
Использование
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?pagename=$matches[1]&food=$matches[2]&variety=$matches[3]', 'top' );
// нужно указать ?p=123 если такое правило создается для записи 123
// первый параметр для записей: p или name, для страниц: page_id или pagename
// скажем WP, что есть новые параметры запроса
add_filter( 'query_vars', function( $vars ){
$vars[] = 'food';
$vars[] = 'variety';
return $vars;
} );
}
При использовании $matches[], ключи массива начинаются с 1, а не 0. Как и положено в регулярных выражениях.
Теперь нужно обновить правила перезаписи, для этого зайдите в настройки ЧПУ и просто обновите настройки - правила обновятся в опциях ВП.
Получить параметры в коде страницы можно через функцию get_query_var(). Например, ссылка: /nutrition/sup/risoviy
echo get_query_var('food'); // > sup
echo get_query_var('variety'); // > risoviy
По умолчанию WordPress не распознает новые переменные запроса, используемые для перезаписи. Для этого нужно их зарегистрировать при помощи функции add_rewrite_tag() или через фильтр query_vars, если этого не сделать, правило перезаписи работать не будет.
Чтобы правило начало работать, нужно обновить (сбросить) правила в БД. Для этого нужно вызвать функцию flush_rules(). Или просто зайти в Настройки -> Постоянные ссылки там автоматически сработает flush_rules().
#2 ЧПУ для дочерней страницы
В параметр 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');.
#3 ЧПУ для страницы (пример 2)
Еще один пример создания ЧПУ для постоянной страницы. Сначала код:
## Правило перезаписи для страницы sitemap
add_action( 'init', 'rewrite_rule_my' );
function rewrite_rule_my(){
add_rewrite_rule( '^(sitemap)/([^/]*)/?', 'index.php?pagename=$matches[1]&pagetype=$matches[2]', 'top' );
add_rewrite_tag( '%pagetype%', '([^&]+)' );
}
Тут мы создавали ЧПУ для постоянной страницы /sitemap?pagename=value (pagename - переменная запроса). После размещения этого кода в functions.php, начнет работать ЧПУ вида: /sitemap/value и в PHP на этой странице, можно будет использовать переменную $wp_query->query_vars['pagetype'], которая будет содержать в себе значение value. Или значение можно получить так: get_query_var('pagetype').
#4 Перенаправление на файл, отличный от index.php
Использование правил перезаписи для перенаправления на скрипты, отличные от index.php.
Аргумент $redirect работает иначе при перенаправлении на НЕ index.php PHP-скрипт. В этом случае WordPress передает эти перенаправления в .htaccess вместо того, чтобы обрабатывать их самостоятельно.
По этой причине переменные следует записывать как $1 вместо $matches[1].
add_action( 'init', 'custom_rewrite_rule', 10, 0 );
function custom_rewrite_rule() {
add_rewrite_rule( 'nutrition/([^/]*)/([^/]*)/?', 'path/to/script.php?food=&variety=', 'top' );
}
При добавлении такого правила -- см. WP_Rewrite::add_rule() -- WP проверяет наличие index.php в параметре $redirect -- см. свойство WP_Rewrite::$index -- если его нет, управление передается методу WP_Rewrite::add_external_rule().
Он добавляет правило перезаписи в отдельный массив non_wp_rules: см. WP_Rewrite::$non_wp_rules. В дальнейшем данные из этого массива будут попадать непосредственно в .htaccess.
То есть, после установки приведенного выше кода и обновления правил перезаписи у вас появится новое правило (строка 7) в .htaccess:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteRule ^nutrition/([^/]*)/([^/]*)/? /path/to/script.php?food=&variety= [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPressДружественная ссылка для входа в систему
Это просто пример, не имеющий практического применения. WordPress начиная с версии 3.0 автоматически перенаправляет на /wp-login.php, если мы пытаемся перейти на /login.
// Let's make http://site.com/login count as a request for http://site.com/wp-login.php
add_action( 'init', 'wp_pretty_login' );
function wp_pretty_login() {
add_rewrite_rule( 'login$', 'wp-login.php', 'top' );
}
После установки этого кода, если мы введем http://example.com/login в строку браузера, то откроется страница входа http://example.com/wp-login.php (URL не изменится - перенаправления не будет):
В .htaccess получим следующее:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteRule ^login$ /wp-login.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Заметки
- Global. WP_Rewrite. $wp_rewrite WordPress rewrite component.
Список изменений
| С версии 2.1.0 | Введена. |
| С версии 4.4.0 | Array support was added to the $query parameter. |
Код add_rewrite_rule() add rewrite rule WP 6.9
function add_rewrite_rule( $regex, $query, $after = 'bottom' ) {
global $wp_rewrite;
$wp_rewrite->add_rule( $regex, $query, $after );
}