Entendiendo add_rewrite_rule
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)

Una regla básica que funcionaría para tu ejemplo:
function wpd_foo_rewrite_rule() {
add_rewrite_rule(
'^foo/([^/]*)/?',
'index.php?pagename=$matches[1]¶m=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.

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.

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.

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.

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.

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/*).

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.

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.

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?
