Modificar el bucle principal de contenido de WordPress con query_posts

Como sabemos los que trabajamos con WordPress, los posts los representa dentro de un “loop” o bucle, con una determinada estructura. Pero quizá en alguna ocasión necesitemos cambiar este comportamiento, bien porque queramos representar tipos personalizados, bien porque queramos encontrar una entrada concreta, ¡O bien porque nos de la gana y punto! Puede haber mil razones. Si este es tu caso, continúa leyendo.

Nunca me cansaré de decir esto: si queréis saber más, tooodo está en el Codex de WordPress. Ahí podéis ampliar información y conocimientos, si sabéis inglés.

Volvamos a lo que nos ocupa. WordPress funciona con una estructura parecida a esta:

<?php
if ( have_posts() ) :
	while ( have_posts() ) : the_post();
		// Aquí se trata el bucle (the_loop) y se muestra la información.
	endwhile;
else :
	echo wpautop( 'Lo siento, no se han encontrado entradas.' );
endif;
?>

El primer “if” comprueba si hay posts. ¿En qué? En la sección en la que estemos entrando. Claro, si tienes tipos personalizados, probablemente esto no funcione como debería. Luego, “the_post” se encargaría de recuperar la información del siguiente post, actualizar el bucle (conocido como “The Loop“) y ponerla a disposición de funciones como “the_title” o “the_content“.

Puedes usar la función “get_posts“, pasándole los parámetros de tu consulta, y luego tratar los resultados con un foreach. Pero ya no es lo mismo, no está “implícito” en WordPress.

Y aquí viene nuestro as en la manga. Una forma de modificar esto sin demasiada complicación es la funcion query_posts. Esta función modifica el flujo normal de noticias que debería aparecer en la página en la que estamos. Es la forma más sencilla, pero no la más eficiente, de hacerlo (según WPCodex, la mejor forma de hacerlo sería usando el hook pre_get_posts y alterando la consulta principal usando is_main_query, pero nosotros hoy vamos a ver la función query_posts).

query_posts admite un parámetro donde vamos a establecer las opciones. Podemos hacerlo con un string o con un Array. Si lo hacemos con un string, los parámetros tendremos que encadenarlos mediante el símbolo &

query_posts('post_name=entrada-de-prueba');

Es posible mantener los parámetros ya existentes de la consulta principal si queremos. Para esto, debemos declarar la variable global $query_string; y encadenarla a un string que pasaremos como parámetros a query_posts:

global $query_string;
query_posts( $query_string . '&order=ASC' );

En caso de que no queramos, no necesitamos $query_string.

Alguno de los parámetros que podemos establecer son el título de la entrada (‘post_title’), el slug (‘post_name’), el tipo de entrada (‘post_type’)… Si tenéis taxonomías personalizadas, también es posible incluírlas, estableciendo el slug de la taxonomía y el valor que debería tener.

Veamos un ejemplo:

$args = Array(
    "post_name"=>"entrada-de-ejemplo",
    "taxonomia-personalizada"=>"valor-de-taxonomia",
    "post_type"=>"tipo-personalizado",
    "orderby"=>"ID",
    "order"=>"DESC",
    "posts_per_page"=>5,
    "paged"=>1
);
query_posts($args);

Hemos incluído “orderby” (ordenar por campo), “order” (Ascendente o Descendente), “posts_per_page” (cuantos posts deben aparecer por página) y “paged” (la página en la que estamos). Estos y muchos más ejemplos los tenéis en… muy bien, lo habéis adivinado, en el Codex.

Podemos completar el ejemplo uniendolo al primer código que vimos:

$args = Array(
    "post_name"=>"entrada-de-ejemplo",
    "taxonomia-personalizada"=>"valor-de-taxonomia",
    "post_type"=>"tipo-personalizado",
    "orderby"=>"ID",
    "order"=>"DESC",
    "posts_per_page"=>5,
    "paged"=>1
);
query_posts($args);

if ( have_posts() ) :
    while ( have_posts() ) : the_post();  // Al entrar en el bucle, cargamos la información del siguiente post
	// Aquí tratamos la información del post. Ahora podemos usar funciones como "the_title()" para obtener el título,
        // o the_content() para obtener el contenido del post. Ahora WordPress funciona como lo haría normalmente, pero
        // con nuestra consulta personalizada.
    endwhile;
else :
	echo wpautop( 'Lo siento, no se han encontrado entradas.' );
endif;

¿Lo habéis entendido? Si tenéis alguna duda, debajo de esta entrada tenéis un formulario de comentarios que os viene que ni pintado para preguntar lo que queráis. ¡Hasta la próxima!

¿Te ha gustado el artículo?
Sé el primero en calificar esta publicación.
1 Star2 Stars3 Stars4 Stars5 Stars
Loading...
Artículo escrito por

¡Exprésate! Dejanos tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

9 Comentarios

Daniel

Saludos tengo una inquietud, Necesito optener los post publicados hoy y los de ayer, susesibamente, Espero su respuesta

Dario

Hola, le hago una consulta. Yo quiero mostrar las entradas de manera aleatoria, creo que en su blog está la solución para mi problema, pero me podría decir cual es el archivo que debo modificar. Quiero decir en que archivo debo poner los códigos que usted acá presenta de manera muy detallado. Desde ya muchas gracias.

Julio

Hola!, mi duda es la siguiente. Tengo un tipo personalizado con campos personalizados en su interior. Uno de esos campos personalizados es "orden" con el slug "orden". Es de tipo numérico y en él pongo la posición que quiero que ocupe. En el loop de archive.php trato de hacer la consulta pero no me sale nada. Lo he hecho utilizando este código: query_posts('meta_key=orden&orderby=meta_value'); while (have_posts()) : the_post(); ¿Alguien sabría decirme qué está fallando?. Muchas gracias

Jorge Vargas

Gracias Juan, pensaba que quizás poder utilizar is_calendar() o get_calendar() y actuar: elseif ( is_month() ) { if is_calendar(){ Aquí redirigir otro archivo.php }endif } Quizás intervenir el widget Calendar o crear una funcion. Seguiré buscando.

Juan

Ya veo el problema. Ambos widgets comparten el resultado de "archive.php", pero en uno queremos que se muestren todas las categorías (en el de Calendario) y en el otro (Archivos) no queremos que se muestre la categoría 7. Lo más sencillo parece ser que archive.php detecte si la petición la está haciendo el widget Calendario, y entonces redirigir o cambiar la consulta. El problema ahora es como hacer que wordpress sepa quién está haciendo uso de ese archivo... Quizá sea más fácil utilizar un plugin (propio o del repositorio de plugins de Wordpress) que no utilice "archives.php" para obtener la lista de entradas, si no que la genere de forma independiente, ¿Lo has pensado? Seguiré investigando, a ver si doy con una solución... Si la encuentras antes que yo, por favor, dinosla, y aprendemos todos :)

Jorge Vargas

Juan: Gracias por tu comentario y solución. Lo que he realizado es agregar el loop en la condición if (is_day()) de archive.php de esta forma: elseif ( is_day() ) {?> <?php while ( have_posts() ) : the_post(); get_template_part( 'content', 'single' ); endwhile; Funciona muy bien al hacer clic en cualquier día del calendario ya que ahora me muestra el post de ese día específico. La dificultad que tengo ahora es cuando le doy clic (en el mismo calendario) al mes siguiente o anterior me muestra todos los post publicados en ese mes, menos la categoría 7 (porque la excluí de archive.php) : La categoría 7 la excluí porque al utilizar el Widget "archivos" deseo que me muestre los post publicados del mes de todas las categorías MENOS la 7. Quizás pueda crear una condición en "archive.php" en la parte elseif ( is_month() ) - Para que reconozca que la consulta viene de Widget "Calendario" y lo mande a otro archivo (ej.: mes-calendario.php) Nuevamente te agradezco por tu dedicación y ayuda

Juan

Buenas Jorge, Creo que me hacen falta más datos para poder ayudarte, o a lo mejor no lo he entendido del todo bien. Hasta donde he entendido, tienes - El archivo "archive.php" modificado para que excluya la categoria id=7 (supongo que esto lo has hecho con query_posts). - Un widget de calendario que muestra solo los posts de una categoría específica en el calendario. - Al pulsar en un día, se ejecuta el loop de archive.php. Si lo he entendido bien, tu problema es que en el calendario muestras los posts de la categoría excluida (la 7), y al pulsar en un día, te lleva a archive.php para mostrar las entradas de ese día, y como está excluida, no se muestra nada. ¿Es esto? Veamos... De alguna forma debes poder diferenciar que estás en la categoría 7. Ya sea por una url concreta, o porque se lo pases como parámetro. Teniendo este dato y el día que has pulsado en el calendario, en lugar de simplemente excluir la categoria, separa casos con if: if( /* Categoria == 7 */ ){ /* Aqui con query_posts puedes establecer que las entradas sean solo de la categoría 7 y del día concreto seleccionado. Luego hacer un nuevo loop que muestre estas entradas. */ } else { /* Aquí iria el código que ya tienes, el que excluye la categoría 7 del loop normal. */ } Espero que te sirva de ayuda. Si no he entendido bien el problema, te agradecería que me lo aclarases un poco e intentaremos ayudarte :)

Jorge Vargas

Buen post. Mi consulta es la siguiente: El archivo "archive.php" lo modifique para excluir una categoría (ID=7) porque dicha categoría quiero mostrarla en una consulta mensual y no general. Tengo un widget modificado del calendario por defecto de wordpress que me permite mostrar los post de una categoría específica. Cuando le doy clic en un dia determinado va al archivo archive.php y ejecuta el loop. Sin embargo al ocupar el widget "archivos" (que me muestra los post por mes) tambien ocupa el archivo archive.php pero como he excluido la categoría "7" entonces no muestra nada. ¿Puedo modificar la condicion del is_day() para incluir además otra condicion? ¿Quizás enviar a otro archivo y personalizar un loop? Espero haberme explicado bien. Agradeceré alguna respuesta de quién esté interesado.

northgoaresorts.co.in

Great site you have here but I was wanting to know if you knew of any community forums that cover the same topics talked about in this article? I'd really like to be a part of online community where I can get opinions from other knowledgeable individuals that share the same interest. If you have any suggestions, please let me know. Kudos!