ACTUALIZACIÓN
Desde que se escribió este núcleo de WordPress, se agregó el enlace 'do_parse_request'
que permite que el enrutamiento de URL se maneje con elegancia y sin la necesidad de extender la clase WP
. Cubrí el tema en profundidad en mi charla de 2014 WordCamp en Atlanta titulada " Hardcore URL Enrutamiento " ; Las diapositivas están disponibles en el enlace.
RESPUESTA ORIGINAL
Diseño de URL ha sido importante por más de una década; Incluso escribí un blog al respecto hace varios años. Y mientras que WordPress es una suma, es un poco de software brillante desafortunadamente su sistema de reescritura de URL no es un problema mental (IMHO, claro. :) De todos modos, me alegra ver a la gente preocuparse por el diseño de URL!
La respuesta que voy a proporcionar es un complemento al que estoy llamando WP_Extended
que es una prueba de concepto para esta propuesta en Trac (Tenga en cuenta que la propuesta comenzó como una cosa y se convirtió en otra, por lo que debe leerla completa para ver hacia dónde se dirigía).
Básicamente, la idea es subclasificar la clase WP
, reemplazar el método parse_request()
y luego asignar la variable global $wp
con una instancia de la subclase. Luego, dentro de parse_request()
usted realmente inspecciona la ruta por segmento de ruta en lugar de usar una lista de expresiones regulares que deben coincidir con la URL en su totalidad.
Entonces, para expresarlo de manera explícita, esta técnica inserta la lógica frente a parse_request()
que verifica las coincidencias de URL a RegEx y en su lugar primero busca coincidencias de términos de taxonomía, pero SOLAMENTE reemplaza a parse_request()
y deja intacto todo el resto del sistema de enrutamiento de URL de WordPress, incluido el uso de la variable $query_vars
.
Para su caso de uso, esta implementación sólo compara segmentos de ruta de URL con términos de taxonomía ya que eso es todo lo que necesita. Esta implementación inspecciona los términos de taxonomía que respetan las relaciones de término padre-hijo y cuando encuentra una coincidencia, asigna la ruta URL (menos las barras diagonales iniciales y finales) a $wp->query_vars['category_name']
, $wp->query_vars['tag']
o $wp->query_vars['taxonomy']
& $wp->query_vars['term']
y omite el método parse_request()
de la clase WP
.
Por otra parte, si la ruta de la URL no coincide con un término de una taxonomía que ha especificado, se delega la lógica de enrutamiento de URL al sistema de reescritura de WordPress llamando al método parse_request()
de WP
class.
Para usar WP_Extended
para su caso de uso, deberá llamar a la función register_url_route()
desde el archivo functions.php
de su tema, de este modo:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
Aquí se encuentra el código fuente del complemento:
<?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();
P.S. CUEVA # 1
Aunque para un sitio determinado, creo que esta técnica funciona de manera brillante, pero NUNCA se debe usar para distribuir un complemento en WordPress.org para que otros lo usen . Si está en el núcleo de un paquete de software basado en WordPress, entonces eso podría estar bien. De lo contrario, esta técnica debería limitarse a mejorar el enrutamiento de la URL para un sitio específico .
¿Por qué? Porque solo un complemento puede utilizar esta técnica . Si dos complementos intentan usarlo, entrarán en conflicto entre sí.
Aparte de esto, esta estrategia se puede expandir para manejar genéricamente prácticamente todos los patrones de casos de uso que podrían requerirse y eso es lo que pretendo implementar tan pronto como encuentre el tiempo libre o un cliente que pueda patrocinar el el tiempo que tomaría construir implementaciones totalmente genéricas.
CAVEAT # 2
Escribí esto para anular parse_request()
, que es una función muy grande, y es muy posible que me haya perdido una propiedad o dos del objeto global $wp
que debería haber configurado. Entonces, si algo funciona, deja que Yo lo sé y me complacerá investigarlo y revisar la respuesta si es necesario.
De todos modos ...