Listar posts de dos categorías en WordPress
¿Qué pasa si queremos mostrar los posts que pertenezcan a dos categorías a la vez? por ejemplo, mostrar los posts que sean de “PHP” y de “Noticias” o “PHP” y “Ejemplos”.
La forma de hacerlo es fácil, primero debemos crearnos la estructura del permalink y que WordPress lo reconozco, en este caso será /categories/slug-category-A/slug-category-B. Para ello tenemos que dar de alta esta estructura el el $wp_rewrite y añadir la variable cats en los parámetros tratados por WordPress.
// Crea la estructura para el rewrite
function categories_rewrite_rules() {
global $wp_rewrite;
$rewrite_tag = '%categories%';
// En la variable cats se almacenará 'slug-category-A/slug-category-B' que luego trataremos
$wp_rewrite->add_rewrite_tag( $rewrite_tag, 'categories/([^/]+/[^/]+)', 'cats=' );
$rewrite_keywords_structure = $wp_rewrite->root . "$rewrite_tag/";
$new_rule = $wp_rewrite->generate_rewrite_rules( $rewrite_keywords_structure );
$wp_rewrite->rules = $new_rule + $wp_rewrite->rules;
return $wp_rewrite->rules;
}
// Permitimos que la variable cats se tenga en cuenta en las queries (URL) de WordPress
function categories_variables( $public_query_vars ) {
$public_query_vars[] = 'cats';
return $public_query_vars;
}
// Hacemos un flush para que tenga en cuenta la nueva regla en el rewrite
function me_flush_rewrite_rules() {
global $wp_rewrite;
$wp_rewrite->flush_rules();
}
add_action( 'init', 'me_flush_rewrite_rules' );
add_action( 'generate_rewrite_rules', 'categories_rewrite_rules' );
add_filter( 'query_vars', 'categories_variables' );
Vale, ya tenemos creada la estructura, ahora solo falta modificar la query para que tenga en cuenta la nueva condición: que el post tenga la categoría A y la categoría B, para lo cual modificaremos el join de la query añadiendo un left join para cada categoría
add_filter( 'posts_join' , 'categories_join' );
function categories_join( $join ) {
global $wpdb, $wp_query;
if (get_query_var('cats')) {
// Recuperamos los slugs de las categorias
$cats = explode('/', $wp_query->query_vars['cats']);
$ids = array();
// Por cada slug recuperamos la categoría y añadimos left join
foreach($cats as $i=>$c) {
$obj = get_category_by_slug($c);
if ($obj) {
$ids[] = $obj->term_id;
$join .= " JOIN {$wpdb->term_relationships} r{$i} on r{$i}.object_id = {$wpdb->posts}.ID and r{$i}.term_taxonomy_id = {$obj->term_id} ";
}
}
}
return $join;
}
Y ya está, si accedieramos a nuestro blog http://miblog.com/categories/php/noticias veríamos los posts que están dentro de PHP y Noticias, con su paginación y demás.
Si por un casual queremos utilizar una template en particular para esto, tan solo deberemos añadir lo siguiente a nuestro functions.php:
function categories_template() {
if (get_query_var('cats')) {
include (TEMPLATEPATH . '/category-videos.php');
exit;
}
}
add_action('template_redirect', 'categories_template');
O si queremos obtener el título de las categorías, podremos crearnos una función que nos lo devuelva:
function get_cats_names() {
if (get_query_var('cats')) {
$cats = explode('/', get_query_var('cats'));
$names = array();
foreach($cats as $i=>$c) {
$obj = get_category_by_slug($c);
if ($obj) {
$names[] = $obj->name;
}
}
return implode(' | ', $names);
}
return '';
}
Últimamente el número de frameworks para PHP que aparecen crece cada vez más rápido. Solar es un framework para PHP5 que nos permite desarrollar aplicaciones web de forma rápida. Usa conceptos derivados del sistema de plantillas
Exelente, es lo que habÃa buscado hace tiempo y no me acuerdo si pude hacerlo, jeje.
Va para favoritos!!!
Y crees que se podrÃa adaptar ésto para usar una categorÃa y una etiqueta al mismo tiempo? En verdad quiero usar una custom taxonomy junto a una etiqueta concreta, lo ves factible?
Hola Txema
Se podrÃa hacer si usas get_term_by.
En vez de usar un foreach, usarÃas el código para el primer elemento de $cats y para el segundo harÃas casi lo mismo, obtienes el objeto (que realmente es un array) mediante la llamada:
$obj = get_term_by('slug' $cats[1], 'post_tag');Espero que te ayude
Saludos
Gracias, tengo que probarlo.
Por cierto, me suena que poniendo /category/cat1+cat2/ puedes obtener directamente los posts que están en esas dos categorÃas, y si en lugar de ‘+’ pones ‘,’ tienes los que son de una, u otra.
Gracias Txema por la información, busqué como loco en Google para saber si habÃa forma de hacerlo y parece que no busqué bien del todo 🙁