Elimine la barra de taxonomía de un enlace permanente de taxonomía jerárquica personalizada

19

Creé una taxonomía de 'foro', usando estas reglas:

register_taxonomy(
  'forum',
  array('topic'),
  array(
    'public' => true,
    'name' => _a('Forums'),
    'singular_name' => _a('Forum'),
    'show_ui' => true,
    'show_in_nav_menus' => true,
    'hierarchical' => true,

    'labels' => array(
      'name' => _a('Forums'),
      'singular_name' => _a('Forum'),
      'search_items' => _a('Search Forums'),
      'popular_items' => _a('Popular Forums'),
      'all_items' => _a('All Forums'),
      'parent_item' => _a('Parent Forum'),
      'parent_item_colon' => _a('Parent Forum:'),
      'edit_item' => _a('Edit Forum'),
      'update_item' => _a('Update Forum'),
      'add_new_item' => _a('Add New Forum'),
      'new_item_name' => _a('New Forum Name'),
    ),
    'query_var' => true,
    'rewrite' => array('slug' => 'forums', 'with_front' => false, 'hierarchical' => true),  
  )
);

En el extremo frontal, las URL parecen:

forums/general-discussion/sub-forum

¿Cómo puedo eliminar la barra frontal ("foros")? Es decir, cambiar las URL a:

general-discussion/sub-forum

Si paso un argumento de slug vacío a register_taxonomy () funciona, pero eso causa problemas con los enlaces permanentes del tipo de publicación asociado con esta taxonomía

    
pregunta onetrickpony 15.02.2011 - 18:05

9 respuestas

10

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 ...

    
respondido por el MikeSchinkel 23.02.2011 - 05:40
7

Simple, en serio.

Paso 1: Deje de usar el parámetro de reescritura. Vamos a rodar tus propias reescrituras.

'rewrite'=>false;

Paso 2: establece reglas de página detalladas. Esto obliga a las Páginas normales a tener sus propias reglas en lugar de ser un catch-all en la parte inferior de la página.

Paso 3: crea algunas reglas de reescritura para manejar tus casos de uso.

Paso 4: forzar manualmente que ocurran reglas de descarga. La forma más fácil: vaya a configuración- > permalink y haga clic en el botón Guardar. Prefiero esto sobre un método de activación de plugin para mi propio uso, ya que puedo forzar que las reglas se desactiven cada vez que cambie las cosas.

Por lo tanto, el tiempo de código:

function test_init() {
    // create a new taxonomy
    register_taxonomy(
        'forum',
        'post',
        array(
            'query_var' => true,
            'public'=>true,
            'label'=>'Forum',
            'rewrite' => false,
        )
    );

    // force verbose rules.. this makes every Page have its own rule instead of being a 
    // catch-all, which we're going to use for the forum taxo instead
    global $wp_rewrite;
    $wp_rewrite->use_verbose_page_rules = true;

    // two rules to handle feeds
    add_rewrite_rule('(.+)/feed/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');
    add_rewrite_rule('(.+)/(feed|rdf|rss|rss2|atom)/?$','index.php?forum=$matches[1]&feed=$matches[2]');

    // one rule to handle paging of posts in the taxo
    add_rewrite_rule('(.+)/page/?([0-9]{1,})/?$','index.php?forum=$matches[1]&paged=$matches[2]');

    // one rule to show the forum taxo normally
    add_rewrite_rule('(.+)/?$', 'index.php?forum=$matches[1]');
}

add_action( 'init', 'test_init' );

¡Recuerda que después de agregar este código, debes tenerlo activo cuando vayas a limpiar las reglas de enlace permanente (guardando la página en Configuración- > Permalinks)!

Una vez que hayas eliminado las reglas y guardado en la base de datos, entonces / lo que sea que vaya a tu foro = cualquier página de taxonomía.

Las reglas de reescritura realmente no son tan difíciles si entiendes las expresiones regulares. Utilizo este código para ayudarme cuando los depuro:

function test_foot() {
    global $wp_rewrite;
    echo '<pre>';
    var_dump($wp_rewrite->rules);
    echo '</pre>';
}
add_action('wp_footer','test_foot');

De esta manera, puedo ver las reglas actuales de un vistazo en mi página. Solo recuerde que, dada cualquier URL, el sistema comienza en la parte superior de las reglas y pasa por ellas hasta que encuentra una que coincida. Luego, la coincidencia se utiliza para volver a escribir la consulta en un conjunto de valores? Clave = de aspecto más normal. Esas claves se analizan en lo que se incluye en el objeto WP_Query. Simple.

Editar: nota al margen, este método probablemente solo funcionará si tu estructura de publicación personalizada normal comienza con algo que no es un complemento, como% category% o algo así. Debe iniciarlo con una cadena estática o un número, como% año%. Esto es para evitar que atrape su URL antes de que llegue a sus reglas.

    
respondido por el Otto 24.02.2011 - 02:30
4

No podrás hacer esto solo con WP_Rewrite, ya que no puede distinguir entre las babosas de término y las de postboca.

También tiene que enlazar con 'request' y evitar el 404, configurando la variable de consulta de publicación en lugar de la taxonomía.

Algo como esto:

function fix_post_request( $request ) {
    $tax_qv = 'forum';
    $cpt_name = 'post';

    if ( !empty( $request[ $tax_qv ] ) ) {
        $slug = basename( $request[ $tax_qv ] );

        // if this would generate a 404
        if ( !get_term_by( 'slug', $slug, $tax_qv ) ) {
            // set the correct query vars
            $request[ 'name' ] = $slug;
            $request[ 'post_type' ] = $cpt_name;
            unset( $request[$tax_qv] );
        }
    }

    return $request;
}
add_filter( 'request', 'fix_post_request' );

Tenga en cuenta que la taxonomía debe definirse antes del tipo de publicación.

Este sería un buen momento para señalar que tener una taxonomía y un tipo de publicación con la misma consulta var es una mala idea.

Además, no podrás acceder a publicaciones que tengan la misma babosa que uno de los términos.

    
respondido por el scribu 18.02.2011 - 01:43
2

Le echaría un vistazo al código del complemento para gatos de nivel superior:

enlace

Usted podría adaptar eso fácilmente, por lo que está buscando su taxonomía personalizada cambiando el

$category_base = get_option('category_base');

en la línea 74 a algo como:

$category_base = 'forums';
    
respondido por el Pabline 15.02.2011 - 18:17
2

Sugeriría echar un vistazo al complemento de Public Permalinks de publicaciones personalizadas . No tengo tiempo para hacer pruebas en este momento, pero puede ayudar con su situación.

    
respondido por el Travis Northcutt 17.02.2011 - 23:11
2

Ya que estoy familiarizado con su otra pregunta , Contestaré con eso en mente.

No he probado esto en absoluto, pero podría funcionar si lo ejecutas una vez justo después de registrar todos los permisos que deseas:

class RRSwitcher {
  var $rules;
  function RRSwitcher(){
    add_filter( 'topic_rewrite_rules', array( $this, 'topics' ) );
    add_filter( 'rewrite_rules_array', array( $this, 'rules' ) );
  }
  function topics( $array ){
    $this->rules = $array;
    return array();
  }
  function rules( $array ){
    return array_merge( (array)$array, (array)$this->rules );
  }
}
$RRSwitcher = new RRSwitcher();
global $wp_rewrite;
$wp_rewrite->use_verbose_rules = true;
$wp_rewrite->flush_rules();

Lo que hace esto: elimina las reglas de reescritura generadas a partir de los temas, enlace permanente del flujo normal de la matriz de reglas y las vuelve a combinar al final de la matriz. Esto evita que esas reglas interfieran con otras reglas de reescritura. A continuación, obliga a las reglas de reescritura detalladas (cada página obtiene una regla individual con una expresión regular específica). Esto evita que las páginas interfieran con las reglas de tu tema. Finalmente, ejecuta una descarga física (asegúrate de que tu archivo .htaccess sea grabable, de lo contrario no funcionará) y guarda la gran variedad de reglas de reescritura muy complicada.

    
respondido por el John P Bloch 18.02.2011 - 00:00
2

Hay un complemento para esto .

Quita el slug de tipo agregando una regla específica para cada página de tipo de publicación personalizada.

    
respondido por el Adam Bell 26.11.2011 - 17:28
2

No estoy seguro de si esto funcionará para taxonomías, pero funcionó para tipos de publicaciones personalizados

Aunque no se ha actualizado durante 2 años, el siguiente complemento funcionó para mí: enlace

Para tu información, estoy ejecutando WP 3.9.1 con WP Types 1.5.7

    
respondido por el Max 22.06.2014 - 17:25
2

Utilice una barra inclinada como valor para slug ... 100% de trabajo

'rewrite' => array(
    'slug'       => '/', 
    'with_front' => FALSE
 ),
    
respondido por el Sathish Jayaraman 09.04.2015 - 15:01

Lea otras preguntas en las etiquetas