WordPress : Loop o Bucle de WordPress

Fecha Publicación:       29 de Agosto de 2022
Fecha Modificación:       15 de Septiembre de 2022

→ Ir a la Documentación oficial de Loop   

El Loop o bucle es una porción de código PHP que usa WordPress para mostrar contenido (post / publicación).

 Para mostrar informacion dinamica dentro de cualquier plantilla de wordpress debemos de usar un loop o bucle.

 → Cuando abrimos cualquier contenido en wordpress internamente wordpress hace una consulta a su base de datos para obtener sus contenido y se guarda en una variable para despues imprimirlo dentro del loop o bucle.

 → En una pagina solo encontrara un unico contenido que es la informacion de esa pagina.

 → Pero si voy en una categoria especifica vere todo los post o articulos de esa categoria.

 → Llamamos loop o bucle al código PHP que usaremos en los archivos de plantilla de nuestro tema para mostrar posts.

 → Según la página que carguemos en el navegador, WordPress sabrá qué posts debe cargar, pero no las mostrará en nuestro HTML a menos que incluyamos un loop o bucle que defina dónde y en qué formato se mostrarán las publicaciones.

 → Cuando hablamos de posts, me refiero a cualquier tipo de contenido o posts, no necesariamente entradas , sino también páginas, custom post types y attachments.  

→ Cualquier código que incluyamos en el loop (bucle) se repetirá la cantidad de veces correspondiente a la publicación que se muestra en la página actual.

El loop o bucle de WordPress se ve así:

Código básico de Loop de WordPress

<?php
 if ( have_posts( ) ){   /* si existen post */
      while ( have_posts( ) ){   /* hacemos un recorrido de los post */ 
         /* the_post() recuperar información referida a la entrada específica usando 
             cualquier Template Tag de WordPress */
        the_post( );   /* imprimimos el post - */      
      }   
  }else{
    echo "No hay posts";
  }
?>

Lo que hace este código:

  • Se empieza con una condicional y dentro la función have_posts() comprueba si existe contenido a mostrar, esta condicional se puede usar con un else para mostrar un mensaje alternativo informando que no existe contenido a mostrar.
  • Se usa una estructura de bucle o loop a través del while, que comprueba nuevamente la función have_posts() cada vez que se realiza una interacción.
  • La función the_post() es llamada dentro del bucle, con esto se mueve el puntero al registro actual y por lo tanto dentro del bucle podemos recuperar información referida a la entrada específica usando cualquier Template Tag de WordPress.

El Loop es el corazón de tu Tema

Todo tema que siga las guías de desarrollo de WordPress tiene como elemento central al Loop de WordPress. Si somos capaces de entender el Loop, seremos capaces de hacer que WordPress se comporte y visualice contenidos de la manera en la que nosotros queremos que lo haga.

El Loop es la conexión entre los datos que tenemos en la base de datos MySQL y el HTML que se renderiza en el navegador. Siempre que visualizamos una entrada o página, WordPress usará el Loop.

Ejemplos Loop o Bucle de WordPress

Ejemplo 1

<?php
if ( have_posts() ) :
  while ( have_posts() ) : 
    the_post(); ?>
    <div class="entrada">
      <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> 
      <div class="contenido">
        <?php the_content(); ?>
      </div>
    </div> <?php
  endwhile; 
endif;
?>

Ejemplo 2

<div id="<?php the_ID(); ?>" <?php post_class('page_post'); ?> >
  <?php 
    if ( has_post_thumbnail() ){
   ?>
    <div class="publication">
        <a href="<?php the_permalink( ); ?>" 
           title="<?php the_title_attribute(); ?>">
	   <?php the_post_thumbnail() ?>
	</a>
     </div>
    <?php } ?>
        <a href="<?php the_permalink(); ?>" 
         title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>
  ?>
</div> <!-- div.phpid -->

Ejemplo 3

<?php
 if ( have_posts( ) ){   /* si existen post */
    if( is_home() ){
      while ( have_posts( ) ){   /* hacemos un recorrido de los post */ 
         /* the_post() recuperar información referida a la entrada específica usando 
             cualquier Template Tag de WordPress */
        the_post( );   /* imprimimos el post - */      
        get_template_part('content');
      }
    }
  }else{
    echo "No hay posts";
  }
?>

Ejemplo 4

<?php
/**
 * The template for displaying pages
 */
get_header(); ?>
<div class="row">
  <div class="col-md-12">
    <?php
    if (have_posts()) :
      // Start the loop.
      while (have_posts()) : the_post();
    ?>
        <article <?php post_class(); ?>>
          <div class="entry-header">
            <?php the_title('<h1 class="entry-title">', '</h1>'); ?>
          </div>
          <div class="entry-content">
            <?php the_content(); ?>
          </div>
        </article>
    <?php
      // End of the loop.
      endwhile;
    else :
      echo wpautop('Lo siento, no se han encontrado entradas.');
    endif;
    ?>
  </div>
</div>
<?php get_footer(); ?>

Analizando el codigo Ejemplo 4

 → El primer « if ( have_posts() ) : » comprueba si hay posts ,  si hay posts WordPress pasará a

→ while ( have_posts() ) : generamos un bucle que se repetirá tantas veces como posts corresponda cargar en la página. Este bucle finaliza con endwhile;.

 → Dentro del bucle nos encontraremos con la función 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«.

Templates Tags usados en el código anterior:

  • post_class(): Devuelve las clases CSS estándard de WordPress para un artículo , es una funcion de wordpress que detectara donde hemos insertado un articulo y le aplicara una serie de estilos. Devuelve las clases CSS estándard de WordPress para un artículo.
  • the_title(): Devuelve el título del artículo.
  • the_content(): Devuelve el contenido del artículo.

 

Los Templates Tags anteriores imprimen directamente el contenido, también puedes usar Template Tags que sólo devuelven el valor, por ejemplo : get_post_class(), get_the_title(), get_the_content()

Es posible que, para mantener mejor organizado el código, dentro del bucle encuentras también referencias a archivos externos a través de la función get_template_part()

<?php
if ( have_posts() ) :	
	while ( have_posts() ) : the_post();
		get_template_part( 'template-parts/post/content', get_post_format() );
	endwhile;
endif;

 

En lugar de imprimir un código HTML directamente, podrías por ejemplo ejecutar algún Shortcode que te brinde la imagen de banner con la función do_shortcode()

Ejemplo 5 Creando Custom Post type carrusel

Vea el tutorial Creando Custom Post type carrusel  donde se usa un ejemplo de loop 

Ejemplo 6 Listar productos Relacionados

          <?php $args = array(
               'post_type'      => 'producto',
               'posts_per_page' => '6',
               'order'          => 'ASC',
               'orderby'        => 'title'
           );
           $productos = new WP_Query($args); ?>
           
          <?php if($productos->have_posts()){ ?>
               
               <div class="row text-center justify-content-center productos-relacionados">
                   <div class="col-12">
                    <h3>Productos Relacionados</h3>
                   </div>
                   <?php while($productos->have_posts()){ ?>
                       <?php  $productos->the_post(); ?>
                        <div class="col-2 my-3 text-center">
                            <?php the_post_thumbnail('thumbnail'); ?>
                            <h4>
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </h4>
                        </div>
                       <?php } ?>
               </div>
           
           <?php } ?>

pregunta?

Hola, me pasa algo raro. Debajo del producto, en lugar de listarme el resto de productos relacionados, me lista las entradas de la categoría novedades. 

Si en el argumento post_type te equivocas en digitarlo por ejemplo escribes post-type  por ende te debe estar tomando el post_type por defecto que es post  y te mostrara  las entradas de las categorias

¿Qué puede mostrar el loop?

Estas son algunas de las funciones disponibles dentro del loop y que nos devuelve información sobre el post, page o Custom Post Type actual:

  • next_post_link(): Enlace al siguiente post publicado cronológicamente
  • previous_post_link(): Enlace al anterior post publicado cronológicamente
  • the_category(): La categoría o categorías asociadas al post actual
  • the_author(): El Autor del post actual
  • the_content(): El contenido principal del post actual
  • the_excerpt(): El extracto del post actual
  • the_post_thumbnail(): La imagen destacada del post actual
  • the_ID(): El ID del post actual
  • the_meta(): Los campos personalizados asociados al post actual
  • the_shortlink(): El enlace corto del post actual
  • the_tags(): La etiqueta o etiquetas asociadas al post actual
  • the_title(): El título del post actual
  • the_time(): La fecha en la que se ha creado el post actual

Además, podemos usar conditional tags para por ejemplo maquetar nuestro contenido o añadir clases específicas según nuestras necesidades:

  • is_home(): Devuelve true si la pagina actual es la home
  • is_admin(): Devuelve true si un administrador está logueado y visitando la página
  • is_single(): Devuelve true si la pagina actual es el detalle de un post
  • is_page(): Devuelve true si la pagina actual es el detalle de una página
  • is_page_template(): Devuelve true si la pagina actual es una plantilla específica, por ejemplo: is_page_template(‘page-contact.php’)
  • is_category(): Devuelve true si la pagina actual es una categoría. Puede especificarse una en concreto, por ejemplo: is_category(‘noticias’)
  • is_tag(): Devuelve true si la pagina actual es una etiqueta
  • is_author(): Devuelve true si la pagina actual es el detalle de autor o si un autor específico está visitando la página
  • is_search(): Devuelve true si la pagina actual es la página de resultados de búsqueda
  • is_404(): Devuelve true si la pagina actual es página no encontrada o página no existe
  • has_excerpt(): Devuelve true si la pagina o post actual tiene extracto

Esto es en esencia el loop de WordPress. Tenemos también funciones para interactuar con él o modificarlo a nuestro antojo como query_posts(), rewind_posts()…y varios hooks para crear nuestras propias funciones y engancharnos a ellos como pre_get_posts, the_post y found_posts.

Aportes mostrar los productos relacionados

Hola. Comparto mi código para que el loop de los productos relacionados no muestre el producto que se está visualizando actualmente. Para lograrlo utilice el hook get_the_ID y una sentencia IF.

  <!-- Productos Relacionados -->
  <?php
    $ID_producto_actual = get_the_ID();
    $args = array(
      'post_type'       => 'producto',
      'posts_per_page'  => 6,
      'order'           => 'ASC',
      'orderby'         => 'title'
    );
    // En la siguiente variable se define el contenido
    // que vamos a solicitar a la base de datos, a través
    // del array de argumentos previamente definidos.
    // Ahora la variable $productos es un objeto con la configuración
    // necesaria para solicitar contenido.
    $productos = new WP_Query($args);
  ?>
  <!-- Ejecutar el loop con el objeto $productos -->
  <?php if($productos->have_posts()) { ?>
    <div class="row justify-content-center productos-relacionados">
      <div class="col-12">
        <h3 class="my-3 text-center">Productos relacionados</h3>
      </div>
      <?php while($productos->have_posts()) { ?>
        <?php $productos->the_post(); ?>
        <?php if(get_the_ID() != $ID_producto_actual) { ?>
          <div class="col-2 my-3 text-center">
            <?php the_post_thumbnail('thumbnail'); ?>
            <h4>
              <a href="<?php the_permalink(); ?>">
                <?php the_title(); ?>
              </a>
            </h4>
          </div>
        <?php } ?>
      <?php } ?>
    </div>
  <?php } ?>

Es una buena idea, para no darle contenido repetido a los usuarios.
Te paso otra opción que te evita hacer el condicional.
Al Loop de Productos Relacionados, le podés agregar este argumento nuevo:

'post__not_in'  => array($ID_producto_actual)

Con el atributo post__not_in, el loop evita todos los post que tengan un ID incluido dentro de ese array.

una mejor manera de hacer la parte del loop es el siguiente:

<?php if(have_posts()): ?>
        <?php while(have_posts()): the_post(); ?>
            <h1 class="my-3"><?php the_title();?></h1>

            <p class=""><?php the_content();?></p>
        <?php endwhile;?>
    <?php endif; ?>

Les comparto el código ya integrando la opción que Carlos dio:

<?php get_header(); ?>

<main class='container'>
        <h1> <?php the_title(); ?> </h1>

        <?php if (have_posts()) {
          while (have_posts()) {
            the_post(); ?>
        <div class="row my-5">
          <div class="col-md-6 col-12">
            <?php the_post_thumbnail('large'); ?>
          </div>
          <div class="col-md-6 col-12">
            <?php the_content(); ?>
          </div>
        </div>
        <?php
    $ID_producto_actual = get_the_ID();
    $args = array(
      'post_type'       => 'producto',
      'posts_per_page'  => 3,
      'order'           => 'ASC',
      'orderby'         => 'title'
    );
    // En la siguiente variable se define el contenido
    // que vamos a solicitar a la base de datos, a través
    // del array de argumentos previamente definidos.
    // Ahora la variable $productos es un objeto con la configuración
    // necesaria para solicitar contenido.
    $productos = new WP_Query($args);
  ?>
  <!-- Ejecutar el loop con el objeto $productos -->
  <?php if($productos->have_posts()) { ?>
    <div class="row text-center justify-content-center productos-relacionados">
      <div class="col-12">
        <h3 class="my-3 text-center">Producto relacionado</h3>
      </div>
      <?php while($productos->have_posts()) { ?>
        <?php $productos->the_post(); ?>
        <?php if(get_the_ID() != $ID_producto_actual) { ?>
          <div class="col-4 my-3 text-center">
            <?php the_post_thumbnail('thumbnail'); ?>
            <h4>
              <a href="<?php the_permalink(); ?>">
                <?php the_title(); ?>
              </a>
            </h4>
          </div>
        <?php } ?>
      <?php } ?>
    </div>
  <?php } ?>

      <?php } ?>
    <?php } ?>
</main>

<?php get_footer(); ?>

Hola. Noté que en los productos relacionados también aparece el producto que se está visualizando en ese momento, creo que no debería mostrarse el mismo producto como relacionado de sí mismo.

Para solucionarlo utilice el hook get_the_ID(), el cual lo almacené en la variable $ID_producto_actual; para obtener el ID del producto que se está visualizando actualmente.

Después dentro del while del loop de los productos relacionados; mediante un if pregunto si el ID del producto que se está visualizando es diferente que el ID de todos los productos del post type productos, si es diferente sigue ejecutándose el código, si el ID es igual sale y continúa con los siguientes productos.

Aquí el código:

<!-- Productos Relacionados -->
  <?php
    $ID_producto_actual = get_the_ID();
    $args = array(
      'post_type'       => 'producto',
      'posts_per_page'  => 6,
      'order'           => 'ASC',
      'orderby'         => 'title'
    );
    // En la siguiente variable se define el contenido
    // que vamos a solicitar a la base de datos, a través
    // del array de argumentos previamente definidos.
    // Ahora la variable $productos es un objeto con la configuración
    // necesaria para solicitar contenido.
    $productos = new WP_Query($args);
  ?>
  <!-- Ejecutar el loop con el objeto $productos -->
  <?php if($productos->have_posts()) { ?>
    <div class="row justify-content-center productos-relacionados">
      <div class="col-12">
        <h3 class="my-3 text-center">Productos relacionados</h3>
      </div>
      <?php while($productos->have_posts()) { ?>
        <?php $productos->the_post(); ?>
        <?php if(get_the_ID() != $ID_producto_actual) { ?>
          <div class="col-2 my-3 text-center">
            <?php the_post_thumbnail('thumbnail'); ?>
            <h4>
              <a href="<?php the_permalink(); ?>">
                <?php the_title(); ?>
              </a>
            </h4>
          </div>
        <?php } ?>
      <?php } ?>
    </div>
  <?php } ?>

También podes agregar el argumento

'post__not_in' => 'ID_producto_actual'

quedando

$args = array(
    	'post_type'       => 'producto',
     	'posts_per_page'  => 6,
     	'order'           => 'ASC',
      	'orderby'         => 'title',
	'post__not_in' => 'ID_producto_actual'
 );

Comparto mi código, que resume lo que se hizo en la clase y las adecuaciones propuestas.

<?php get_header(); ?>
<main class="container">
    <h1><?php the_title(); ?></h1>

    <?php if(have_posts()){
            while(have_posts()){ the_post();
    ?>

    <div class="row my-5">
        <div class="col-md-6 col-12">
            <?php the_post_thumbnail('large')?>
        </div>
        <div class="col-md-6 col-12">
            <?php the_content();?>
        </div>
    </div>
    <?php }
        } ?>
        <?php $ID_producto_actual = get_the_ID(); ?>
        <?php $args = array(
            'post_type' => 'producto',
            'posts_per_page' => -1,
            'post__not_in'   => array($ID_producto_actual),
            'order'     => 'ASC',
            'orderby' => 'title'
        );
        $productos = new WP_Query($args); ?>
        <?php if ($productos->have_posts()) { ?>
        <div class="row text-center justify-content-center productos-relacionados">
            <div class="col-12">
                <h3>Productos relacionados</h3>
            </div>
            <?php while($productos->have_posts()) { ?>
                <?php $productos->the_post(); ?>
                <div class="col-md-2 col-12 my-3 text-center">
                    <figure><?php the_post_thumbnail('thumbnail'); ?></figure>
                    <h4 class='my-2'>
                        <a href="<?php the_permalink();?>">
                            <?php the_title(); ?>
                        </a>
                    </h4>
                </div>
            <?php } ?>
        </div>
        <?php } ?>
</main>
<?php get_footer(); ?>

Otro Aporte sobre argumentos :

$args = [ //array con los parámetros de Wordpress
	'post_type' => 'post', // nompre del tipo de post 	'post_mime_type' => '', // si el post_type es attachment, en este campo se puede filtrar un tipo de imagen por su mimetype	// Caso multiple array('post', 'page')
	'posts_per_page' => 5, // Cantidad de post que va a mostrar
	'offset' => 0, // De los primeros cuantos va a omitir
	'category' => '', // elegir categoría por id
	'category_name' => '', // elegir categoria por nombre
    'tax_query' => [ // Elegir por termino de una categoria
        'relation' => 'or', // solo requerido si es múltiple        
        [
            'taxonomy' => 'my_custom_taxonomy',
            'terms' => 7,
            'include_children' => false // Remove if you need posts from term 7 child terms
        ],
        [
            'taxonomy' => 'my_custom_taxonomy_2',
            'terms' => 8,
            'include_children' => false // Remove if you need posts from term 7 child terms
        ],        
    ],
	'date_query' => [
		'column' => 'post_date',
		'after' => '2012-04-01',
		'before' => '2012-04-30' 
	], // Filtro por entre fechas de publicación del posts
	'orderby' => 'menu_order', // ordenar segun algo https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters
	'order' => 'desc', // ordenar de forma desc o asc
	'include' => '', // incluir por id cualquier post que no cumplan con el filtro
	'exclude' => '996, 665', // excluir por id
	'meta_key' => '', // filtra por el campo personalizado
	'meta_value' => '', // filtra por el campo personalizado
	'post_parent' => '', // id del post padre
	'author' => '', // filtrar por el id del autor
	'author_name' => '', // filtrar por el nombre del autor
	'post_statusf' => 'publish', // solo las que están publicadas
	'suppress_filters' => true // activa los filtros de correcciones que hace Wordpress de forma automática
];

$myposts = get_posts( $args ); // Agarra toda la informacion de los post

Para evitar que se muestre el producto que se está visualizando, lo hice de esta forma más simple:

<?php $ID_producto_actual = get_the_ID(); ?> // Añadí esta linea
                <?php $args = array(
                    'post_type'         => 'producto',
                    'posts_per_page'    => 6,
                    'post__not_in'      => array($ID_producto_actual), // Y aquí un array
                    'order'             => 'ASC',
                    'orderby'           => 'title'
                );

Para los golegas que depronto les pueda pasar… Les comento que, para que les tenga en cuenta el nuevo argumento “‘post__not_in’ => array($ID_producto_actual)”, primero deben inicializar la variable $ID_producto_actual = get_the_ID();

Quedando así!

$ID_producto_actual = get_the_ID();
$args = array(
‘post_type’ => ‘producto’, /* Traer tipo de contenido: producto /
‘posts_per_page’ => 6, / Traer max 6 productos para mostrar /
‘order’ => ‘ASC’, / En orden Ascentende /
‘orderby’ => ‘title’, / Tome el titulo para ordenarlo /
‘post__not_in’ => array($ID_producto_actual) / para evitar repetir el mismo producto que estamos viendo a detalle */
);

revisa este codigo esta repetido parece mas arriba

<!-- Productos Relacionados -->
  <?php
    $ID_producto_actual = get_the_ID();
    $args = array(
      'post_type'       => 'producto',
      'posts_per_page'  => 6,
      'order'           => 'ASC',
      'orderby'         => 'title'
    );
    // En la siguiente variable se define el contenido
    // que vamos a solicitar a la base de datos, a través
    // del array de argumentos previamente definidos.
    // Ahora la variable $productos es un objeto con la configuración
    // necesaria para solicitar contenido.
    $productos = new WP_Query($args);
  ?>
  <!-- Ejecutar el loop con el objeto $productos -->
  <?phpif($productos->have_posts()) { ?>
    <divclass="row justify-content-center productos-relacionados">
      <divclass="col-12">
        <h3class="my-3 text-center">Productos relacionados</h3>
      </div>
      <?phpwhile($productos->have_posts()) { ?>
        <?php $productos->the_post(); ?>
        <?phpif(get_the_ID() != $ID_producto_actual) { ?>
          <divclass="col-2 my-3 text-center">
            <?php the_post_thumbnail('thumbnail'); ?>
            <h4>
              <ahref="<?php the_permalink(); ?>">
                <?php the_title(); ?>
              </a>
            </h4>
          </div>
        <?php } ?>
      <?php } ?>
    </div>
  <?php } ?>
Articulo : 1171 - Veces Leidas
Compartir Articulo:
×

¡Apóyame suscribiéndote a mi canal!

Tutoriales sobre Diseño Web