Entendiendo add_rewrite_rule

31 dic 2016, 01:34:12
Vistas: 52.3K
Votos: 21

Estoy tratando de hacer funcionar add_rewrite_rule para extraer un parámetro de la URL y pasarlo a través de la solicitud. He visto varios posts sobre esto, pero no logro hacerlo funcionar.

Si una URL comienza con una cadena específica, me gustaría eliminarla de la URL y pasarla como parámetro de consulta.

URL de ejemplo:

http://domain.com/foo/my_page

Esto se transformaría en

http://domain.com/my_page?param=foo

Si 'foo' no está presente, debería procesarse como una solicitud normal. Esta lógica debería aplicarse a cualquier URL de página o URL de tipo de publicación personalizada en mi sitio (básicamente foo/*). La idea es que actúe como un paso intermedio, si la URL tiene 'foo', eliminarlo y luego dejar que WordPress continúe con su comportamiento normal.

Ya tengo 'param' incluido en los query_vars permitidos.

En total, necesitaría funcionar para los siguientes casos:

  • /foo/my_page (Página)
  • /foo/my_folder/my_page (Subpágina)
  • /foo/example_type (Archivo de Post Personalizado)
  • /foo/example_type/example_post (Post Personalizado Individual)
2
Comentarios

¿cualquier URL, es decir, publicaciones, categorías, etiquetas, etc., no solo el tipo de publicación page, o simplemente cualquier página? ¿qué pasa con las páginas padre/hijo en la jerarquía?

Milo Milo
31 dic 2016 02:05:08

@Milo Lo he aclarado para ti. Solo estoy usando páginas y tipos de publicaciones personalizados (páginas de archivo y páginas individuales).

Louis W Louis W
31 dic 2016 02:07:00
Todas las respuestas a la pregunta 2
8
17

Una regla básica que funcionaría para tu ejemplo:

function wpd_foo_rewrite_rule() {
    add_rewrite_rule(
        '^foo/([^/]*)/?',
        'index.php?pagename=$matches[1]&param=foo',
        'top'
    );
}
add_action( 'init', 'wpd_foo_rewrite_rule' );

Esto toma lo que venga después de foo/ y lo establece como pagename para la consulta, y luego param obtiene el valor estático foo. Si necesitas diferentes patrones de URL, necesitarás reglas adicionales para cada patrón único. Consulta la documentación de WP_Query para ver las distintas variables de consulta que se pueden establecer dentro de las reglas de reescritura. No olvides limpiar las reglas de reescritura después de añadir nuevas. Esto se puede hacer visitando la página de Configuración de Enlaces Permanentes.

Ahora, al visitar tu URL de ejemplo:

http://domain.com/foo/my_page

se cargará la página correcta, pero no se comportará exactamente igual que visitar:

http://domain.com/my_page?param=foo

porque cuando se usan reescrituras internas, param se establece dentro del objeto de consulta $wp_query, no en la superglobal $_GET. Si necesitas trabajar con código que busca un valor en $_GET, necesitarás un paso adicional para establecer ese valor:

function wpd_foo_get_param() {
    if( false !== get_query_var( 'param' ) ){
        $_GET['param'] = get_query_var( 'param' );
    }
}
add_action( 'parse_query', 'wpd_foo_get_param' );

Otro método a considerar es usar endpoints, de modo que /foo/ esté al final de las URL en lugar de como prefijo. La ventaja de esto es que la API add_rewrite_endpoint simplifica añadir todas las reglas que necesitas, incluyendo la habilitación de paginación.

2 ene 2017 05:15:52
Comentarios

Gracias por la explicación detallada. Parece estar cerca, funciona para páginas pero me da un error 404 para las URLs de archivos y entradas individuales de publicaciones personalizadas.

Louis W Louis W
2 ene 2017 06:51:46

bueno sí, como dije, necesitas agregar reglas adicionales que coincidan con cada uno de esos patrones. No sé cómo lucen esas URLs en tu configuración.

Milo Milo
2 ene 2017 09:00:13

Tengo un tipo de página personalizada llamado 'projects' que tiene archivos y páginas individuales. ¿Puedes darme un ejemplo para eso? Así podré hacer los demás.

Louis W Louis W
2 ene 2017 18:50:49

Además, no parece funcionar para subpáginas.

Louis W Louis W
2 ene 2017 20:59:03

Correcto, solo funciona para el ejemplo específico que mencioné anteriormente, por eso al final sugiero optar por un endpoint en su lugar. Si necesitas varios niveles de subpáginas, archivos con paginación, publicaciones individuales, etc., terminarás agregando muchas reglas. Este plugin analizador de reescrituras te ayudará a mostrar cómo las reglas se analizan en variables de consulta, y puede darte pistas sobre cómo construir reglas adicionales.

Milo Milo
3 ene 2017 00:08:39

Lo siento, el endpoint no funcionará, necesito que la variable esté al principio de la URL. No intento ser difícil, pero no puedo aceptar esto como una solución hasta que cumpla con los requisitos establecidos en la publicación original, que incluye archivos de publicaciones personalizadas/páginas individuales y (aunque no explícito) debería funcionar para subpáginas (foo/*).

Louis W Louis W
3 ene 2017 00:25:18

Edita tu pregunta para agregar un ejemplo de cada patrón de URL que necesita una regla. Realmente no me preocupa que mi respuesta sea aceptada, a veces puedo hacer que las personas respondan sus propias preguntas dándoles algo con lo que empezar.

Milo Milo
3 ene 2017 02:15:12

Se han agregado ejemplos.

Louis W Louis W
3 ene 2017 04:09:42
Mostrar los 3 comentarios restantes
1

Bien, he conseguido ejemplos funcionales para los 3 tipos de solicitudes. Me tomó mucha experimentación y pruebas para lograr que funcionaran. Supongo que Milo es bueno empujando a la gente a responder sus propias preguntas.

Después de incontables cambios y actualizaciones de los enlaces permanentes, me di cuenta de que era mucho más fácil averiguar las URLs fuera del add_rewrite_url y, una vez que funcionaban, definir la reescritura. Por ejemplo: index.php?param=foo&post_type=example_type.

Algo obvio, pero lo agrego aquí por si ayuda a alguien más. DEBES definir las reglas add_rewrite_rule para tipos de contenido personalizados ANTES de definir tus reglas comodín para páginas/subpáginas. Perdí bastante tiempo con eso y creo que fue lo principal que me impedía entender por qué no funcionaban las reglas.

Aquí están las 3 reglas que funcionan para todas mis necesidades. La regla para Página/Subpágina se combinó en una sola.

// Archivo de contenido personalizado
add_rewrite_rule(
    '^foo/example_type/?$',
    'index.php?param=foo&post_type=example_type',
    'top'
    );

// Contenido personalizado individual
add_rewrite_rule(
    '^foo/example_type/([^/]*)/?$',
    'index.php?param=foo&example_type=$matches[1]',
    'top'
    );

// Páginas, de nivel superior y subpáginas
// Esto DEBE colocarse en el código DESPUÉS de add_rewrite_rule para contenido personalizado
add_rewrite_rule(
    '^foo/(.+)/?$',    
    'index.php?param=foo&pagename=$matches[1]',
    'top'
    );

Adicionalmente, lo que hice fue configurar un bucle para agregar múltiples reglas para tipos de contenido personalizado. Recuerda: debes definir las reglas add_rewrite_rule para tipos de contenido personalizado ANTES de definir tus reglas comodín para páginas/subpáginas.

$custom_types = array('example_type', 'projects', 'people');

foreach($custom_types as $type) {

    // Archivo de contenido personalizado
    add_rewrite_rule(
        '^foo/'.$type.'/?$',
        'index.php?param=foo&post_type='.$type,
        'top'
        );

    // Contenido personalizado individual
    add_rewrite_rule(
        '^foo/'.$type.'/([^/]*)/?$',
        'index.php?param=foo&'.$type.'=$matches[1]',
        'top'
        );

}

El Analizador de reescrituras que Milo compartió fue bastante útil cuando intentaba entender mejor cómo WordPress consulta páginas/entradas.

5 ene 2017 17:51:59
Comentarios

Llego tarde al espectáculo, pero ¿puedo contactarte para otro ejemplo? Eso sí, no entiendo en absoluto el parámetro $tag de add_rewrite_rule. No tengo ni idea de lo que significa. Tampoco entiendo el ejemplo que usa pagename=$matches[1]'. ¿QUÉ? Tengo una URL como domain.com/detail?id=2&it=3. Quiero que la página sea domain.com/detail/2-3/. ¿Estarías dispuesto?

Debbie Kurth Debbie Kurth
10 nov 2019 10:52:42