UPDATE
Desde que este núcleo do WordPress foi escrito, foi adicionado o 'do_parse_request'
hook que permite que o roteamento de URL seja tratado com elegância e sem a necessidade de estender a classe WP
. Eu abordei o tópico em profundidade na minha palestra de 2014 no Atlanta WordCamp intitulada " Hardcore URL Roteamento " ; os slides estão disponíveis no link.
RESPOSTA ORIGINAL
O design de URL tem sido importante por mais de uma década; Eu mesmo escrevi um blog sobre isso vários anos atrás. E enquanto o WordPress é uma soma brilhante de um software infelizmente o seu sistema de reescrita de URL é um pouco curto de morte cerebral (IMHO, claro.:) De qualquer forma, feliz em ver pessoas importando-se com o design de URL!
A resposta que vou fornecer é um plugin que estou chamando de WP_Extended
, que é uma prova de conceito para esta proposta no Trac (Note que a proposta começou como uma coisa e evoluiu para outra, então você tem que ler a coisa toda para ver para onde ela estava indo.)
Basicamente, a ideia é subclassificar a classe WP
, substituir o método parse_request()
e, em seguida, atribuir a variável global $wp
a uma instância da subclasse. Em seguida, dentro de parse_request()
, você inspeciona o caminho pelo segmento de caminho em vez de usar uma lista de expressões regulares que devem corresponder à URL na sua totalidade.
Portanto, para explicitar explicitamente, essa técnica insere lógica na frente do parse_request()
, que verifica as correspondências URL-RegEx e, em vez disso, procura correspondências de termos de taxonomia, mas APENAS substitui parse_request()
e deixa todo o restante do sistema de roteamento de URL do WordPress intacto incluindo e especialmente o uso da variável $query_vars
.
Para seu caso de uso, essa implementação somente compara segmentos de caminho de URL com termos de taxonomia, já que é tudo o que você precisa. Essa implementação inspeciona os termos de taxonomia que respeitam os relacionamentos de termos pai-filho e, quando encontra uma correspondência, atribui o caminho da URL (menos barras iniciais e finais) a $wp->query_vars['category_name']
, $wp->query_vars['tag']
ou $wp->query_vars['taxonomy']
& $wp->query_vars['term']
e ignora o método parse_request()
da classe WP
.
Por outro lado, se o caminho da URL não corresponder a um termo de uma taxonomia que você especificou, ele delega a lógica de roteamento de URL ao sistema de reescrita do WordPress chamando o método parse_request()
da WP
class.
Para usar WP_Extended
para seu caso de uso, você precisará chamar a função register_url_route()
do arquivo functions.php
do seu tema da seguinte forma:
add_action('init','init_forum_url_route');
function init_forum_url_route() {
register_url_route(array('taxonomy'=>'forum'));
}
O que aqui é o código-fonte do plug-in:
<?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. CAVEAT # 1
Embora para um determinado site eu ache que esta técnica funcione brilhantemente mas esta técnica NUNCA deve ser usada para um plugin ser distribuído no WordPress.org para outros usarem . Se é o núcleo de um pacote de software baseado no WordPress, então isso pode ser bom. Caso contrário, essa técnica deve se limitar a melhorar o roteamento de URL para um site específico .
Por quê? Porque apenas um plugin pode usar esta técnica . Se dois plugins tentarem usá-lo, eles entrarão em conflito um com o outro.
Como um aparte, esta estratégia pode ser expandida para lidar genericamente com praticamente todos os padrões de caso de uso que poderiam ser necessários e é isso que pretendo implementar assim que eu encontrar o tempo livre ou um cliente que possa patrocinar o tempo que levaria para construir implementações totalmente genéricas.CAVEAT # 2
Eu escrevi isso para substituir parse_request()
, que é uma função muito grande, e é bem possível que eu tenha perdido uma propriedade ou dois do objeto global $wp
que eu deveria ter definido. Eu sei e ficarei feliz em pesquisar e revisar a resposta, se necessário.
De qualquer forma ...