¿Cómo crear un loop personalizado en WordPress para productos relacionados?
Cuando trabajamos en WordPress, una de las funcionalidades avanzadas que podemos implementar es un loop personalizado para mostrar productos relacionados. Esto nos permite optimizar la experiencia del usuario al ofrecerle productos adicionales que pueden ser de su interés. Vamos a repasar cómo lograrlo paso a paso.
Iniciamos por crear un loop en WordPress mediante el constructor WP_Query. Este constructor nos facilita acceder a nuestros productos en el sitio. A continuación, definimos los atributos necesarios para configurar el loop.
$args=array('post_type'=>'producto',// Definimos que queremos seleccionar productos.'posts_per_page'=>6,// Indicamos cuántos productos queremos mostrar.'orderby'=>'title',// Ordenamos por el título del producto.'order'=>'DESC'// Ordenamiento en orden descendente.);$productos=newWP_Query($args);
¿Cómo verificar y gestionar los resultados del loop?
Ahora que tenemos definido nuestro loop, el siguiente paso es verificar si nuestro objeto contiene productos. Nos valdremos de un condicional y técnicas para tratar los métodos del objeto.
if($productos->have_posts()){echo'<div class="row">';// Iteramos sobre los productos.while($productos->have_posts()){$productos->the_post();// Iniciamos la interfaz de cada producto.echo'<div class="col-md-2 my-3">';the_post_thumbnail('thumbnail');// Mostramos la imagen del producto.// Título con enlace al producto.echo'<h4><a href="'.get_permalink().'">'.get_the_title().'</a></h4>';echo'</div>';}echo'</div>';}else{echo'No se encontraron productos relacionados.';}wp_reset_postdata();// Reiniciamos los datos del post.
¿Qué se debe considerar para la integración de CSS y diseño?
Al momento de diseñar la interfaz, debemos recordar que cada elemento gráfico debe estar correctamente alineado y estilizado. En este ejemplo, usamos clases de Bootstrap para un diseño responsive.
Creamos una fila (row) para contener todos los productos.
Distribuimos cada producto en 2 columnas (col-md-2) para que al usar Bootstrap, se reparta en el espacio.
Utilizamos clases de margen (my-3) para un espaciado uniforme.
Aseguramos que los títulos estén centrados usando text-center.
Adicionalmente, es crucial verificar y cerrar bien todas las etiquetas HTML, así como mantener el código limpio, mejorando para cada ajuste.
Este enfoque no solo mejora la experiencia visual sino también la navegación entre productos, creando un flujo intuitivo para el usuario. En futuras clases se verá cómo personalizar y potenciar aún más esta funcionalidad con taxonomías personalizadas, un área apasionante del desarrollo en WordPress. ¡Sigue atento para conocer más!
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.
<!--ProductosRelacionados--><?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 =newWP_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 }?>
Espero que les sea de utilidad. Saludos!
Está buenísimo Francisco!
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.
Saludos!
Hola Lucio, muchas gracias por el tip! funcionó perfecto y es mucho más entendible ya en el código.
Muchas gracias!!!
una mejor manera de hacer la parte del loop es el siguiente:
es más fácil de leer, se comprende y no se te pierden las llaves de apertura y cierre de php.
Es una buena opción!
Se puede elegir la que resulte más clara. Lo importante es ponerse de acuerdo para mantener una misma forma de trabajo dentro del equipo.
Saludos!
de hecho esa es forma que se recomienda cuando se mezcla php con html, en algún lugar de la documentación lo leí hace años :D
Comparto mi código, que resume lo que se hizo en la clase y las adecuaciones propuestas.
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:
<!--ProductosRelacionados--><?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 =newWP_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 }?>
en la query de productos y este argumento indica que no traiga los post con ese ID.
Podes pasarle un solo ID, o un array con IDs para que no traiga los que necesites :)
Se le pueden pasar unos cuantos argumentos al construcctor de WP_Query
!OMG!
Porque hacemos tantas etiquetas de php?? si todo es codigo php? Gracias!
Para poder intercalar lo con el HTML y que esté más ordenado (para mi gusto).
No es necesario hacerlo de esa forma, pero es la que me resulta mejor y más entendible para el equipo de trabajo.
Acordate que en gran medida escribimos código para otros, no para nosotros mismos, por eso es importante que sea lo más entendible posible.
Saludos!
Gracias por la pregunta! Me gusta la claridad y sencillez de la respuesta
No es una mala práctica poner un loop dentro de otro loop? ademas ni siquiera se usó la función wp_reset_query creo que puede terminar dando resultados extraños en un template más complejo
Hola, cómo estás?
En este caso no, ya que se crea una nueva instancia del objeto WP_Query.
Si lo hiciéramos con query_posts() si sería absolutamente necesario diferenciar los loops. Es recomendable la función wp_reset_postdata() para esos casos. Esta función conserva el loop original y elimina cualquier modificación que hayas hecho sobre el mismo.
De todas formas, crear diferentes instancias de WP_Query es la práctica más recomendada.
Saludos!
Por ejemplo si quieres llamar más abajo del código a la función the_title() a cuál de los loops vas a hacer referencia, no digo que esté mal pero no creo que sea la mejor manera.
Saludos.
Esta clase solo escribe codigo...
De eso se trata para poder aprender.
si pero el problema es que no explican el codigo como tal :/
NO he podido hacer que aparezcan, ni la navegacion, ni los post type en la parte de abajo cuiando se visualiza el producto, he visto los videos por lo menos 5 veces y en ninguna parte se distigue que se hayan dejado de elaborar algun tipo de codigo, agradezco la repuesta para poder seguir avanzando en el curso. Gracias
Hola David, cómo estás?
Podrías subir tu código a un repo y compartirlo para que podamos ayudarte?
Saludos!
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. Este es mi código:
Hola Marcelo, cómo estás?
Veo que dentro de los args usaste post-type en lugar de post_type, por ende te debe estar tomando el post_type por defecto que es post.
Saludos!
Parse error: syntax error, unexpected single-quoted string "orderby", expecting ")" in C:\xampp\htdocs\superromantico\wp-content\themes\superromantico\single-producto.php on line 21
¿les ha ocurrido que la palabra 'orderby' no esta referenciada ?
Hola Erick, cómo estás?
El problema no es con la palabra "orderby", sino que te dice que es inesperada y que esperaba encontrar un paréntesis. Probablemente te está faltando cerrar un array antes de avanzar con la siguiente propiedad.
Espero que esta info te sirva.
Saludos!
Preguntas: ¿Cómo hacer para que si tengo una página que presenta los productos por categorías en woocommerce, al hacer click en una de ellas me lleve a otra página con las subcategorías pertenecientes a esta? Me explico tengo la categoría Móviles y Tablets y la subcategoría Móviles y otra subcategoría Tablets, entonces lo que quiero es que cuando haga click en Móviles y Tablet, me cargue una página con todas las subcategorías de esta y así hasta llegar al/los productos deseados.
Segunda: ¿Cómo puedo añadir un elemento de busqueda en woocomerce pero sin plugin? Me refiero a que en la página de productos no me sale la opción de buscar por nombre o lo que le indique y me gustaría implemntearlo.
Gracias a tod@s.
Para tu segunda duda si no haces uso de un puglin tendrías que hacer la programación directa del elemento para que haga una búsqueda.
Gracias @alexcamachogz
que bueno poder mostrar los productos relacionados, hasta ahora nada nuevo en este curso vs el de curso practico de wp
Cuando se trata de elegir qué plantillas usar para cada página, lo primero que hará WordPress es verificar qué tema estás usando. Cada tema incluye su propio conjunto de archivos de plantilla que tendrá prioridad sobre todos los demás. Eso es parte de lo que llamamos la «jerarquía de plantillas» (en inglés, WordPress Hierarchy) de WordPress en acción, que es algo que vamos a explorar en la siguiente sección.
Si intentas cargar la página de una hipotética categoría de hosting, por ejemplo, esto es lo que sucede en segundo plano:
WordPress buscará un archivo de plantilla llamado category-hosting.php en el directorio de tu tema actual.
Si no hay un archivo category-hosting.php, WordPress buscará uno que use la ID de la categoría en su lugar, como category-2.php.
Si WordPress no encuentra ninguna de esas opciones, buscará un archivo genérico category.php en su lugar.
Si no encuentra un archivo llamado category.php, WordPress volverá a intentar y buscará la plantilla archive.php.
Finalmente, si todo lo demás falla, la plataforma cargará el archivo index.php de tu tema y lo usará como la plantilla de la página.
Aquí les dejo mi nota personal con todos los argumentos que he utilizado, capas encuentras el que necesitas para tu proyecto:
$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
Buenos días, ¿cómo logro que mis otras páginas lean las entradas (categorías)? No logro que las lea
Hola Melany, cómo estás?
A qué te referís con que otras páginas puedan leer tus entradas?
Poder insertarlas? Dentro de algunas clases veremos cómo poder utilizarlas por AJAX y por medio de la API de WP.
Si no era esa tu duda, podés volver a explicarme la duda?
Saludos!
Lucio, estoy pegada en un loop de mis productos y llevo un par de horas buscando el bug ¿me puedes ayudar?
<?php get_header();?><main class="container"><h1>Este producto es:<?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 $args =array('post_type'=>'producto','posts_per_page'=>6,'order'=>'ASC','orderby'=>'title'); $productos =newWP_Query($args);?><?php if($productos->have_posts()){?><div class="row justify-content-productos-relacionados"><?php while($productos->have_posts()){?><?php $productos->the_posts();?><div class="col-2 my-3"><?php the_post_thumbnail('thumbnail');?></div><?php }//Cierre while have_post ?></div><?php }//Cierre del if have_post ?><?php //Cierre del while }}//Cierre del if ?></main><?php get_footer();?>```
Hola Jenny! Cómo estás?
Mirá, podés revisar el código en este enlace.
De todas formas, el error es que antes de comenzar el Loop nuevo, tenés que terminar el anterior. Es decir que tenés que cerrar el primer while antes de comenzar el segundo.
Por lo que veo en el código, solo con mover el cierre del while a la línea anterior a donde empezás a definir $args, debería andar correctamente.
Saludos!
Jenny, otra cosa que no había notado es que en los div estás usando divclass y mainclass todo junto y en realidad van separados, es decir <div class="clase"> y <main class="clase">```.
No se si es por el copiado y pegado dentro del comentario o si es que lo ten'es así en el código, pero eso también hay que corregirlo.
Saludos!
Todo perfectamente claro. Gracias
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');