¿Bucle dentro de un bucle?
Estoy usando un par de bucles wp_query personalizados en mi página, el primero recupera noticias de una determinada categoría y luego muestra un pequeño extracto con el enlace permanente.
El segundo es otro wp_query que obtiene un tipo de entrada personalizada con algunos campos personalizados avanzados.
El problema es que me gustaría tener otro bucle dentro del segundo que obtenga 3 entradas de la sección de noticias con una miniatura (básicamente lo opuesto al primer bucle, obtendrá todas las otras categorías). Después de leer innumerables artículos sobre el bucle, no puedo entender cómo hacer un bucle 'anidado' dentro de mi segundo bucle. Estoy seguro de que tiene que ser simple, parece algo que sería fácil de hacer.
Aquí está mi código con mucho HTML eliminado.
<?php
/*
* Nombre de la Plantilla: Página de inicio
*/
?>
<?php get_header(); ?>
<div class="thenews">
<div class="newsinner">
<div class="grid-1">
<h6 class="nsix">últimas noticias</h6>
</div> <!-- fin div grid-1 -->
<div class="grid-2">
<?php
$recentPosts = new WP_Query();
$recentPosts->query('cat=5&showposts=1');
?>
<?php while ($recentPosts->have_posts()) : $recentPosts->the_post(); ?>
<p><?php echo ''.get_the_twitter_excerpt(); ?>...</p>
</div> <!-- fin div grid-2 -->
<div class="grid-3">
<a href="<?php the_permalink() ?>">Leer más</a>
<?php endwhile; wp_reset_query(); ?>
</div> <!-- fin div grid-3 -->
</div> <!-- fin div newsinner -->
</div> <!-- fin div thenews -->
<div id="main-content">
<div class="typograhpy">
<div class="home-grid-1">
<div class="home-grid-1-inner">
<?php
$portfolio_query = new WP_Query(array(
'post_type' => 'headerhome',
'showposts' => 1
) );
?>
<?php while ($portfolio_query->have_posts()) : $portfolio_query->the_post(); ?>
<h2><?php the_title(); ?></h2>
<?php the_content(); ?>
<div class="anyres">
<p> <?php the_field('anyresolution'); ?></p>
</div> <!-- fin div anyres -->
</div> <!-- fin home-gird-1-inner -->
</div> <!-- fin home-grid-1 -->
<div class="home-grid-2">
<div class="inner-home-1">
<div class="inside-home-1-1">
<h2><?php the_field('services_'); ?></h2>
<p> <?php the_field('services_text'); ?></p>
</div> <!-- fin div inside-home-1-1 -->
<div class="inside-home-1-2">
<p> <?php the_field('services_text_right'); ?></p>
</div> <!-- fin div inside-home-1-2 -->
</div> <!-- fin div inner-home-1 -->
<div class="margindiv"></div>
<div class="inner-home-2">
<div class="brushpic"></div> <!-- fin div brushpic -->
<h3><?php the_field('services_1_header') ?></h3>
<p><?php the_field('services_1_content'); ?></p>
</div><!-- fin div inner-home-2 -->
<div class="inner-home-3">
<div class="cloudpic"></div> <!-- fin div cloudpic -->
<h3><?php the_field('services_2_header') ?></h3>
<p><?php the_field('services_2_content'); ?></p>
</div> <!-- fin div inner-home-3 -->
<div class="inner-home-4">
<div class="onetwoone"></div> <!-- fin div onetwoone -->
<h3><?php the_field('services_3_header') ?></h3>
<p><?php the_field('services_3_content'); ?></p>
</div> <!-- fin div inner-home-4 -->
</div> <!-- fin div home-grid-2 -->
<div style="clear:both"></div>
</div> <!-- fin div typograhpy -->
<div class="graphgrid">
</div> <!-- fin div graphgrid -->
<div class="sizesdes">
<blockquote><?php the_field('gallery_blockquote_') ?></blockquote>
<p><?php the_field('gallery_content'); ?></p>
<?php endwhile; wp_reset_query(); ?>
</div>
</div><!-- fin div main-content -->
<?php get_footer(); ?>
Código funcional, aunque no recuperará the_post_thumbnail
<?php
global $post;$backup=$post;
$inner_query = new WP_Query();
$inner_query->query('showposts=3');
?>
<?php while ($inner_query->have_posts()) : $inner_query->the_post(); $post=$backup; ?>
<?php the_post_thumbnail(); ?>
<p><?php echo ''.get_the_custom_excerpt(); ?>...</p>
<a href="<?php the_permalink() ?>">Leer más</a>
<?php endwhile; ?>
Puedes crear cualquier número de bucles que desees creando más objetos WP_Query
$query = new WP_Query($args);
while ($query->have_posts()) :
// inicialización para $inner_args & respaldar el post global actual
$inner_query = new WP_Query($inner_args);
while ($inner_query->have_posts()) :
// hacer algo
endwhile;
// restaurar el post global desde el respaldo creado previamente
endwhile;
EXPLICACIÓN COMO SE SOLICITÓ
Cada vez que llamas a una etiqueta de plantilla como the_title();
, muestra algo sobre el post actual en el bucle. Pero ¿cómo sabe cuál post es el actual? Se hace leyendo la información de los datos globales del post (almacenados en una variable global $post
)
Cuando usas un bucle, siempre usas $query->the_post()
como primera declaración. Lo que hace esta función es establecer esos datos globales al siguiente post del objeto WP_Query
(los contenidos previos se pierden)
Aquí, cuando llamaste al bucle interno, los datos del post relacionados con el bucle externo se perdían cuando el bucle interno comenzaba a trabajar. Entonces cualquier función que uses después del final del bucle interno seguirá encontrando solo los datos del bucle interno.
En la solución primero guardaste los datos del bucle externo en otra variable antes de que los contenidos se perdieran. Luego el bucle funciona como se supone que debe hacerlo (eliminando todos los datos del bucle externo).
Luego, cuando el trabajo del bucle interno termina, ahora necesitas usar los datos del bucle externo pero se perdieron debido al bucle interno. Aquí es donde tomas los datos guardados previamente y los reemplazas. Ahora estás de vuelta en la posición en la que estabas cuando comenzaste el bucle interno.

Edite mi primer post, no puedo hacer que esto funcione correctamente. Aunque estoy seguro de que estoy haciendo algo mal.

¿Hiciste backup de los datos globales del post? Agrega global $post;$backup=$post;
antes del while interno y $post=$backup;
después del while interno.

Ah, funciona cuando lo escribo así (ver edición del primer post), pero the_post_thumbnail ya no funciona.

$post=$backup;
va después del bucle while, es decir, después del endwhile;

Ah, correcto, ahora funciona. ¿Puedes explicar qué hace global $post;$backup=$post; en el contexto del bucle? Solo para saber qué estoy haciendo realmente.
¡Y gracias por tu ayuda, lo aprecio!

Puedes usar WP_Query::reset_postdata() para esto también.
$query = new WP_Query($args);
while ($query->have_posts()) :
// inicialización para $inner_args y respaldo del $post global actual
$inner_query = new WP_Query($inner_args);
while ($inner_query->have_posts()) :
// hacer algo
endwhile;
// restaurar el $post global desde el respaldo creado previamente
$query->reset_postdata();
endwhile;

Tu respuesta comienza bien. Por favor considera explicar cómo y por qué este código resuelve el problema para que otros puedan aprender de él. Consulta la guía de respuestas para más consejos.
