MISE À JOUR
Depuis l'écriture, ce noyau WordPress a ajouté le 'do_parse_request'
crochet qui permet au routage d'URL d'être géré avec élégance et sans avoir à étendre la WP
classe. J'ai couvert le sujet en profondeur dans mon exposé WordCamp d'Atlanta 2014 intitulé " Routage d'URL hardcore " ; les diapositives sont disponibles sur le lien.
RÉPONSE ORIGINALE
La conception d'URL est importante depuis plus d'une décennie; J'ai même écrit un blog à ce sujet il y a plusieurs années. Et bien que WordPress soit la somme d'un logiciel génial, malheureusement, son système de réécriture d'URL est juste à court de cervelle (à mon humble avis, bien sûr. :) Quoi qu'il en soit, heureux de voir des gens se soucier de la conception d'URL!
La réponse que je vais fournir est un plugin que j'appelle WP_Extended
qui est une preuve de concept pour cette proposition sur Trac (Notez que la proposition a commencé comme une chose et a évolué en une autre, vous devez donc lire la chose entière pour voir où il était dirigé.)
Fondamentalement, l'idée est de sous- WP
classer la classe, de remplacer la parse_request()
méthode, puis d'affecter la $wp
variable globale avec une instance de la sous-classe. Ensuite, en parse_request()
vous, inspectez réellement le chemin par segment de chemin au lieu d'utiliser une liste d'expressions régulières qui doivent correspondre à l'URL dans leur intégralité.
Donc, pour le dire explicitement, cette technique insère une logique devant celle parse_request()
qui vérifie les correspondances URL-à-RegEx et recherche d'abord des correspondances de termes de taxonomie, mais elle remplace et laisse UNIQUEMENTparse_request()
le reste du système de routage d'URL WordPress intact, y compris et en particulier l'utilisation de la $query_vars
variable.
Pour votre cas d'utilisation, cette implémentation compare uniquement les segments de chemin d'URL aux termes de taxonomie, car c'est tout ce dont vous avez besoin. Cette implémentation inspecte les termes de taxonomie respectant les relations de terme parent-enfant et lorsqu'elle trouve une correspondance, elle attribue le chemin URL (moins les barres obliques de début et de fin) à $wp->query_vars['category_name']
, $wp->query_vars['tag']
ou $wp->query_vars['taxonomy']
& $wp->query_vars['term']
et elle contourne la parse_request()
méthode de la WP
classe.
En revanche, si le chemin URL ne correspond pas à un terme d'une taxonomie que vous avez spécifiée, il délègue la logique de routage URL au système de réécriture WordPress en appelant la parse_request()
méthode de la WP
classe.
Pour l'utiliser WP_Extended
pour votre cas d'utilisation, vous devrez appeler la register_url_route()
fonction à partir du functions.php
fichier de votre thème comme ceci:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Voici le code source du 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
Bien que pour un site donné, je pense que cette technique fonctionne à merveille mais cette technique ne doit JAMAIS être utilisée pour qu'un plugin soit distribué sur WordPress.org pour que d'autres puissent l'utiliser . S'il est au cœur d'un progiciel basé sur WordPress, cela pourrait être correct. Sinon, cette technique devrait se limiter à améliorer le routage d'URL pour un site spécifique .
Pourquoi? Parce qu'un seul plugin peut utiliser cette technique . Si deux plugins essaient de l'utiliser, ils entreront en conflit.
En aparté, cette stratégie peut être étendue pour gérer de manière générique pratiquement tous les modèles de cas d'utilisation qui pourraient être requis et c'est ce que j'ai l'intention de mettre en œuvre dès que je trouve le temps libre ou un client qui peut parrainer le temps qu'il faudrait pour construire des implémentations entièrement génériques.
CAVEAT # 2
J'ai écrit ceci pour remplacer parse_request()
ce qui est une très grande fonction, et il est fort possible que j'ai raté une propriété ou deux de l' $wp
objet global que j'aurais dû définir. Donc, si quelque chose agit de manière chancelante, faites le moi savoir et je serai heureux de recherchez-le et révisez la réponse si nécessaire.
En tous cas...
'slug' => 'forums'
blanc simplement le retirer complètement et simplement l'avoir'rewrite' => array('with_front' => false, 'hierarchical' => true)
? Je pense que cela a fonctionné dans le passé pour moi. Assurez-vous également de vider les permaliens.