ОБНОВИТЬ
С момента написания этого ядра WordPress был добавлен 'do_parse_request'
хук, который позволяет элегантно обрабатывать URL-маршрутизацию без необходимости расширять WP
класс. Я подробно рассказал об этой теме в своем выступлении на WordCamp в Атланте в 2014 году под названием « Жесткая маршрутизация URL » ; слайды доступны по ссылке.
ОРИГИНАЛЬНЫЙ ОТВЕТ
Дизайн URL был важен уже более десяти лет; Я даже написал блог об этом несколько лет назад. И хотя WordPress является суммой, это отличное программное обеспечение, к сожалению, его система перезаписи URL не хватает мозгов (ИМХО, конечно. :) В любом случае, рад видеть людей, заботящихся о дизайне URL!
Ответ, который я собираюсь дать, - это плагин, который я называю, WP_Extended
который является доказательством концепции этого предложения на Trac (обратите внимание, что предложение началось как одно, а превратилось в другое, так что вам нужно прочитать всю вещь, чтобы увидеть, где это было во главе.)
По сути, идея состоит в том WP
, чтобы создать подкласс класса, переопределить parse_request()
метод, а затем назначить глобальную $wp
переменную экземпляром подкласса. Затем внутри parse_request()
вы фактически проверяете путь по сегменту пути, а не используете список регулярных выражений, которые должны полностью соответствовать URL-адресу.
Таким образом, чтобы заявить об этом явно, этот метод вставляет логику перед parse_request()
проверкой совпадений URL-to-RegEx и вместо этого сначала ищет совпадения терминов таксономии, но ТОЛЬКО заменяет parse_request()
и оставляет неповрежденной всю остальную систему маршрутизации URL WordPress, включая и особенно использование $query_vars
переменной.
Для вашего варианта использования эта реализация сравнивает только сегменты пути URL с терминами таксономии, поскольку это все, что вам нужно. Эта реализация инспектирует таксономии терминов уважая родитель-ребенок длительные отношения , и когда он находит совпадение, присваивает URL - путь (минус передней и задней косой черты) , чтобы $wp->query_vars['category_name']
, $wp->query_vars['tag']
или $wp->query_vars['taxonomy']
& $wp->query_vars['term']
и обходит parse_request()
метод WP
класса.
С другой стороны, если путь URL не совпадает с термином из указанной таксономии, он делегирует логику маршрутизации URL в систему переписывания WordPress, вызывая parse_request()
метод WP
класса.
Для использования WP_Extended
в вашем случае вам нужно вызвать register_url_route()
функцию из functions.php
файла вашей темы следующим образом:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Что здесь является исходным кодом для плагина:
<?php
/*
Filename: wp-extended.php
Plugin Name: WP Extended for Taxonomy URL Routes
Author: Mike Schinkel
*/
function register_url_route($args=array()) {
if (isset($args['taxonomy']))
WP_Extended::register_taxonomy_url($args['taxonomy']);
}
class WP_Extended extends WP {
static $taxonomies = array();
static function on_load() {
add_action('setup_theme',array(__CLASS__,'setup_theme'));
}
static function register_taxonomy_url($taxonomy) {
self::$taxonomies[$taxonomy] = get_taxonomy($taxonomy);
}
static function setup_theme() { // Setup theme is 1st code run after WP is created.
global $wp;
$wp = new WP_Extended(); // Replace the global $wp
}
function parse_request($extra_query_vars = '') {
$path = $_SERVER['REQUEST_URI'];
$domain = str_replace('.','\.',$_SERVER['SERVER_NAME']);
//$root_path = preg_replace("#^https?://{$domain}(/.*)$#",'$1',WP_SITEURL);
$root_path = $_SERVER['HTTP_HOST'];
if (substr($path,0,strlen($root_path))==$root_path)
$path = substr($path,strlen($root_path));
list($path) = explode('?',$path);
$path_segments = explode('/',trim($path,'/'));
$taxonomy_term = array();
$parent_id = 0;
foreach(self::$taxonomies as $taxonomy_slug => $taxonomy) {
$terms = get_terms($taxonomy_slug);
foreach($path_segments as $segment_index => $path_segment) {
foreach($terms as $term_index => $term) {
if ($term->slug==$path_segments[$segment_index]) {
if ($term->parent!=$parent_id) { // Make sure we test parents
$taxonomy_term = array();
} else {
$parent_id = $term->term_id; // Capture parent ID for verification
$taxonomy_term[] = $term->slug; // Collect slug as path segment
unset($terms[$term_index]); // No need to scan it again
}
break;
}
}
}
if (count($taxonomy_term))
break;
}
if (count($taxonomy_term)) {
$path = implode('/',$taxonomy_term);
switch ($taxonomy_slug) {
case 'category':
$this->query_vars['category_name'] = $path;
break;
case 'post_tag':
$this->query_vars['tag'] = $path;
break;
default:
$this->query_vars['taxonomy'] = $taxonomy_slug;
$this->query_vars['term'] = $path;
break;
}
} else {
parent::parse_request($extra_query_vars); // Delegate to WP class
}
}
}
WP_Extended::on_load();
PS CAVEAT # 1
Хотя для данного сайта я думаю, что этот метод работает великолепно, но этот метод НИКОГДА не должен использоваться для распространения плагина на WordPress.org для использования другими . Если это ядро программного пакета, основанного на WordPress, тогда это может быть хорошо. В противном случае этот метод должен быть ограничен улучшением маршрутизации URL для конкретного сайта .
Зачем? Потому что только один плагин может использовать эту технику . Если два плагина попытаются использовать его, они будут конфликтовать друг с другом.
Кроме того, эта стратегия может быть расширена, чтобы в целом обрабатывать практически все возможные варианты использования, и это то, что я намереваюсь реализовать, как только я найду свободное время или клиента, который может спонсировать время, которое потребуется для построить полностью общие реализации.
ПЕРЕДАЧА № 2
Я написал это для переопределения, parse_request()
которое является очень большой функцией, и вполне возможно, что я пропустил свойство или два из глобального $wp
объекта, который я должен был установить ... Так что, если что-то будет работать не так, как надо, дайте мне знать, и я буду рад исследуйте это и пересмотрите ответ, если это будет необходимо.
Так или иначе...
'slug' => 'forums'
пустым, просто удалить его и просто иметь'rewrite' => array('with_front' => false, 'hierarchical' => true)
? Я думаю, что это сработало в прошлом для меня. Также убедитесь, что вы стираете постоянные ссылки.