AKTUALIZACJA
Od czasu napisania tego rdzenia WordPress dodano 'do_parse_request'
haczyk, który pozwala na eleganckie zarządzanie routingiem adresów URL bez konieczności rozszerzania WP
klasy. Szczegółowo omówiłem ten temat w moim wykładzie WordCamp 2014 w Atlancie zatytułowanym „ Hardcore URL Routing ” ; slajdy są dostępne pod linkiem.
ORYGINALNA ODPOWIEDŹ
Projektowanie adresów URL było ważne od ponad dekady; Napisałem nawet o tym blog kilka lat temu. I chociaż WordPress to suma, to genialne oprogramowanie, niestety jego system do przepisywania adresów URL nie ma już mózgów (IMHO, oczywiście. :) W każdym razie cieszę się, że ludzie dbają o projektowanie adresów URL!
Mam zamiar udzielić wtyczki, którą nazywam, WP_Extended
która jest dowodem koncepcji tej propozycji na Tracu (zauważ, że propozycja zaczęła się jako jedna rzecz i ewoluowała w inną, więc musisz przeczytać całą rzecz, aby zobaczyć, gdzie to było na czele.)
Zasadniczo chodzi o podklasę WP
klasy, przesłonięcie parse_request()
metody, a następnie przypisanie $wp
zmiennej globalnej instancją podklasy. Następnie w parse_request()
tobie sprawdź ścieżkę według segmentu ścieżki zamiast korzystać z listy wyrażeń regularnych, które muszą pasować do adresu URL w całości.
Tak więc, mówiąc wprost, technika ta wstawia logikę przed parse_request()
sprawdzaniem zgodności adresów URL z RegEx i zamiast tego najpierw szuka dopasowań terminów taksonomicznych, ale TYLKO zastępuje parse_request()
i pozostawia nienaruszoną resztę systemu routingu URL WordPress, w tym i zwłaszcza użycie $query_vars
zmiennej.
W twoim przypadku użycia ta implementacja porównuje tylko segmenty ścieżki URL z warunkami taksonomii, ponieważ to wszystko, czego potrzebujesz. Ta implementacja kontroluje warunki taksonomii poszanowaniem relacji rodzic-dziecko utrzymujące a kiedy znajdzie dopasowanie przypisuje ścieżkę URL (minus początkowe i końcowe ukośniki) do $wp->query_vars['category_name']
, $wp->query_vars['tag']
lub $wp->query_vars['taxonomy']
& $wp->query_vars['term']
i omija parse_request()
sposobu WP
klasie.
Z drugiej strony, jeśli ścieżka adresu URL nie zgadza się z terminem z określonej taksonomii, deleguje logikę routingu adresu URL do systemu przepisywania WordPress, wywołując parse_request()
metodę WP
klasy.
Aby użyć w WP_Extended
przypadku użycia, musisz wywołać register_url_route()
funkcję z functions.php
pliku motywu w następujący sposób:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Co to jest kod źródłowy wtyczki:
<?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
Chociaż dla danej strony myślę, że ta technika działa doskonale, ale NIGDY nie należy jej używać do dystrybucji wtyczki na WordPress.org, z której mogą korzystać inni . Jeśli jest to rdzeń pakietu oprogramowania opartego na WordPress, może to być w porządku. W przeciwnym razie technika ta powinna być ograniczona do poprawy routingu adresów URL dla konkretnej witryny .
Czemu? Ponieważ tylko jedna wtyczka może korzystać z tej techniki . Jeśli dwie wtyczki spróbują go użyć, będą ze sobą konfliktować.
Nawiasem mówiąc, tę strategię można rozszerzyć, aby generalnie obsługiwać praktycznie każdy wzorzec przypadku użycia, który może być wymagany, i właśnie to zamierzam wdrożyć, gdy tylko znajdę wolny czas lub klienta, który może sponsorować czas, który zajmie budować w pełni ogólne implementacje.
CAVEAT # 2
Napisałem to, aby zastąpić parse_request()
tę bardzo dużą funkcję, i jest całkiem możliwe, że przegapiłem właściwość lub dwa globalne $wp
obiekty, które powinienem był ustawić. Więc jeśli coś zadziwia, daj mi znać i chętnie zbadaj go i w razie potrzeby popraw odpowiedź.
Tak czy inaczej...
'slug' => 'forums'
puste, po prostu usuwając je całkowicie i po prostu mając'rewrite' => array('with_front' => false, 'hierarchical' => true)
? Myślę, że to działało w przeszłości dla mnie. Upewnij się także, czy przepłukałeś permalinki.