¿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 '';
}
Vaya, no sabÃa que existÃa 🙂
Yo hace no demasiado programé algo similar, aunque en mi caso estaba más adaptado al proyecto y, sobretodo, era más flexible ya que no sacaba la tarea de la cola siempre, sino cuando las tareas eran del tipo “One Time”, pq habÃa tareas recurrentes tipo “cron” (ejecutate cada hora, cada dÃa, etc).
La verdad es que tu idea me parece bastante acertada, porque hay muchas tareas recurrentes. Supongo que se podrÃa generar una cola especÃfica para cada una de ellas: “tareas_hora”, “tareas_dia”, “tareas_semana” y cuando se lee una tarea (y se saca de la cola, se podrÃa volver a introducir en ella, y asà realizar lo que tu hacÃas.
Saludos