AKTUALISIEREN
Seit dem Schreiben dieses WordPress-Kerns wurde der 'do_parse_request'
Hook hinzugefügt, mit dem das URL-Routing elegant gehandhabt werden kann, ohne dass die WP
Klasse erweitert werden muss. Ich habe das Thema in meinem WordCamp-Vortrag 2014 in Atlanta mit dem Titel " Hardcore URL Routing " ausführlich behandelt . Die Folien finden Sie unter dem Link.
URSPRÜNGLICHE ANTWORT
URL-Design ist seit mehr als einem Jahrzehnt wichtig. Ich habe sogar vor einigen Jahren einen Blog darüber geschrieben . Und obwohl WordPress eine großartige Software ist , ist das URL-Rewrite-System leider nur kurz vor dem Tod (IMHO, natürlich. :) Wie auch immer, ich bin froh, Leute zu sehen, die sich um das URL-Design kümmern!
Die Antwort, die ich geben werde, ist ein Plugin, das ich anrufe und WP_Extended
das ein Proof of Concept für diesen Vorschlag auf Trac ist. (Beachten Sie, dass der Vorschlag als eine Sache begann und sich in eine andere entwickelte. Sie müssen also die gesamte Sache lesen, um zu sehen, wo es ging voran.)
Grundsätzlich besteht die Idee darin, die WP
Klasse in Unterklassen zu unterteilen , die parse_request()
Methode zu überschreiben und dann die globale $wp
Variable mit einer Instanz der Unterklasse zuzuweisen . Dann parse_request()
inspiziere in dir tatsächlich den Pfad nach Pfadsegment, anstatt eine Liste regulärer Ausdrücke zu verwenden, die mit der URL in ihrer Gesamtheit übereinstimmen müssen.
Um es explizit auszudrücken, fügt diese Technik eine Logik ein, vor der parse_request()
nach URL-zu-RegEx-Übereinstimmungen gesucht wird und stattdessen zuerst nach Taxonomiebegriffsübereinstimmungen gesucht wird. Sie ersetzt jedoch NURparse_request()
den gesamten Rest des WordPress-URL-Routingsystems, einschließlich und vor allem die Verwendung der $query_vars
Variablen.
Für Ihren Anwendungsfall vergleicht diese Implementierung nur URL-Pfadsegmente mit Taxonomiebegriffen, da dies alles ist, was Sie benötigen. Diese Implementierung prüft Begriffe Taxonomie Eltern-Kind - Zeitbeziehungen zu respektieren und wenn es eine Übereinstimmung findet es ordnet den URL - Pfad (minus vorderen und hinteren Schrägstriche) zu $wp->query_vars['category_name']
, $wp->query_vars['tag']
oder $wp->query_vars['taxonomy']
& $wp->query_vars['term']
und es umgeht die parse_request()
Methode der WP
Klasse.
Wenn der URL-Pfad andererseits nicht mit einem Begriff aus einer von Ihnen angegebenen Taxonomie übereinstimmt , delegiert er die URL-Routing-Logik durch Aufrufen der parse_request()
Methode von an das WordPress-UmschreibesystemWP
Klasse .
Um WP_Extended
für Ihren Anwendungsfall zu verwenden, müssen Sie die register_url_route()
Funktion aus der functions.php
Datei Ihres Themas folgendermaßen aufrufen :
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Was ist hier der Quellcode für das Plugin:
<?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
Obwohl ich denke, dass diese Technik für eine bestimmte Site hervorragend funktioniert, sollte diese Technik NIEMALS für ein Plugin verwendet werden, das auf WordPress.org verteilt wird, damit andere es verwenden können . Wenn es sich um den Kern eines auf WordPress basierenden Softwarepakets handelt, ist dies möglicherweise in Ordnung. Andernfalls sollte sich diese Technik auf die Verbesserung des URL-Routings für eine bestimmte Site beschränken .
Warum? Weil nur ein Plugin diese Technik anwenden kann . Wenn zwei Plugins versuchen, es zu verwenden, treten Konflikte auf.
Abgesehen davon kann diese Strategie erweitert werden, um praktisch jedes erforderliche Use-Case-Muster generisch zu handhaben, und das werde ich implementieren, sobald ich entweder die freie Zeit finde oder einen Kunden, der die Zeit sponsern kann, die es dauern würde Erstellen Sie vollständig generische Implementierungen.
CAVEAT # 2
Ich habe dies geschrieben, um zu überschreiben, parse_request()
was eine sehr große Funktion ist, und es ist gut möglich, dass ich ein oder zwei der globalen Objekte verpasst habe$wp
Objekts, das ich hätte setzen sollen habe recherchiere es und überarbeite die Antwort, wenn nötig.
Sowieso...
'slug' => 'forums'
leer zu lassen, nur um es zu entfernen und nur zu haben'rewrite' => array('with_front' => false, 'hierarchical' => true)
? Ich denke, das hat in der Vergangenheit bei mir funktioniert. Stellen Sie auch sicher, dass Sie die Permalinks spülen.