Как создать пользовательские URL-маршруты?
У меня есть особое требование, и я надеюсь объяснить его не слишком запутанно. Я создал шаблон страницы, где я перечисляю некоторые объекты недвижимости, которые получаю из внешнего XML-файла. Пока никаких проблем, и допустим URL выглядит так:
http://www.example.com/properties/
Каждый объект недвижимости имеет ссылку, которая должна перенаправлять пользователя на страницу "Отдельный объект", отображающую больше информации о нем. Я хотел узнать, есть ли способ сделать ссылку такой:
http://www.example.com/properties/123
Где 123 будет идентификатором объекта недвижимости. То есть, если у меня есть URL вида properties/some_id, я хочу иметь возможность загружать файл представления (как файлы single.php или page.php), но специфичный для этого условия URL.
Это возможно?
Добавьте это в файл functions.php вашей темы или создайте плагин.
add_action( 'init', 'wpse26388_rewrites_init' );
function wpse26388_rewrites_init(){
add_rewrite_rule(
'properties/([0-9]+)/?$',
'index.php?pagename=properties&property_id=$matches[1]',
'top' );
}
add_filter( 'query_vars', 'wpse26388_query_vars' );
function wpse26388_query_vars( $query_vars ){
$query_vars[] = 'property_id';
return $query_vars;
}
Это добавляет правило перезаписи, которое перенаправляет запросы вида /properties/ с любыми цифрами после на страницу с именем properties, устанавливая переменную запроса property_id. Не забудьте зайти в настройки постоянных ссылок и сохранить их, чтобы обновить правила перезаписи и включить новое правило.
В вашем шаблоне page-properties.php функция get_query_var('property_id') вернёт ID свойства, если он был установлен, в противном случае будет показана стандартная страница свойств.
Это почти сработало для меня, но мне пришлось добавить:
add_filter('init','flushRules');
function flushRules(){
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
tooshel
@tooshel вам точно не стоит сбрасывать правила при каждом запросе - это ресурсоемкая операция, которая может сильно замедлить ваш сайт. Вам нужно сбрасывать правила только один раз - при активации плагина или просто посетив страницу настроек постоянных ссылок.
Milo
Да, я понимаю... но при тестировании очень удобно, когда это есть в коде!
tooshel
Более умное регулярное выражение для перезаписи URL может быть таким: ^properties/([0-9]+)/?. Иначе оно будет совпадать с чем-то вроде example/properties/1
Ryan Taylor
@RyanTaylor ты уверен в этом? При моих тестах оно не захватывает example/properties/1.
Milo
Где должен находиться файл page-properties.php? Я поместил его в директорию плагина. Это правильно?
Farid Movsumov
@FeridMovsumov файлы темы всегда загружаются из директории текущей активной темы, если только вы не добавите фильтр для их загрузки из другого места.
Milo
Привет @Milo, это прекрасный кусок кода. Ты не знаешь, как сделать, чтобы он не конфликтовал при использовании $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; ? Функция перехватывает $page (и оставляет его пустым), и я не могу продолжить пагинацию.
Jaypee
@Milo что ты имеешь в виду под поместить это в плагин? Где именно? В любое место плагина возможно? Или в wp-content/plugins/myPlugin/myPlugin.php ?
SL5net
Другой способ сделать это:
add_action('init', function() {
add_rewrite_rule( '^properties/([0-9]+)/?',
'index.php?pagename=properties&property_id=$matches[1]',
'top' );
}, 10, 0);
add_action('init', function() {
add_rewrite_tag( '%property_id%', '([^&]+)' );
}, 10, 0);
Принятый ответ работает с 4.7 (и 4.8), не уверен, почему вы думаете, что это не так. Ваш код по сути делает то же самое, add_rewrite_tag добавляет переменную запроса в тот же массив, что и фильтр query_vars.
Milo
@Milo возможно, это не сработало для меня, но у меня больше нет версии 4.7 под рукой, так что я не могу проверить. Я отредактирую свой ответ.
Christian Lescuyer
@Milo Хотя лично я предпочитаю тег rewrite, но все же проверил принятый ответ, и он работает. Просто дело вкуса.
Johansson
@JackJohansson правила перезаписи (rewrite tags) необходимы, когда вы используете их в структуре постоянных ссылок (permastruct). Это просто дополнительные данные, которые WordPress в данном случае не использует.
Milo