Múltiplos loops no WordPress podem ser muito úteis para desenvolvedores. Com eles é possível fazer praticamente tudo o que você desejar com o conteúdo do site que você estiver criando, como exibir últimos posts de uma categoria, criar um slider com os posts fixos (sticky), criar widgets dos posts mais comentados, enfim, qualquer coisa…

Neste artigo você vai aprender a criar múltiplos loops na mesma página mantendo o loop padrão do WordPress intacto.

Antes de iniciarmos, se você não tiver afinidade com a criação de temas para WordPress, recomendo a leitura do nosso artigo PHP, HTML e CSS em temas WordPress, nele falamos bastante sobre várias coisas relacionadas com desenvolvimento no CMS.

O loop padrão do WordPress

Qualquer tema WordPress tem pelo menos um loop padrão, já que o mesmo é responsável por controlar todo o conteúdo do site. Não é possível que eu indique qual arquivo contém o loop, porque isso vai depender do desenvolvedor daquele tema. Normalmente, os loops do WordPress ficam em arquivos separados e são incluídos nos arquivos de modelo utilizando a template tag get_template_part.

O loop padrão do WordPress começa com:

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

E termina com:

    <?php endwhile; ?>
<?php endif; ?>

A primeira linha de código verifica se existem posts a serem exibidos. Caso positivo, um laço while é iniciado para exibir todo o conteúdo. O número de artigos exibidos será o mesmo que está configurado nas configurações do seu WordPress pela área administrativa.

Dentro do loop você pode utilizar dezenas de template tags que servem para exibir o conteúdo desejado.

Veja um exemplo bem simples:

<?php if ( have_posts() ): ?> 
    <?php while ( have_posts() ) : the_post(); ?>
    
        <!-- As template tags virão abaixo -->
        <?php the_title();?><br>
        <?php the_content();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

No exemplo acima utilizei duas template tags: the_title e the_content. Sendo uma para exibir o título do conteúdo e a outra para exibir o conteúdo do artigo.

Este é um exemplo simples, mas quando você começa a misturar as template tags com as conditional tags, isso pode ficar bem confuso.

Observação: Existem template tags que só podem ser utilizadas dentro do loop, isso é descrito no WordPress Codex.

Criando mais de um loop

Existem várias maneiras para criar loops no WordPress, você pode até modificar a consulta principal do site utilizando query_posts ou pre_get_posts, mas este não será nosso caso.

Quando você altera a consulta padrão do WordPress, pode ser que você atrapalhe o bom funcionamento das coisas se não souber exatamente o que está fazendo. Por outro lado, você pode utilizar WP_Query para gerar uma nova consulta sem gerar conflito com a consulta principal.

A classe WP_Query suporta milhares de argumentos que vão determinar o que deverá ser exibido. Por exemplo, suponhamos que eu queira exibir apenas posts fixos em um loop separado:

<?php
$nova_consulta = new WP_Query( 
    array( 
        'post__in' => get_option('sticky_posts'),
    ) 
);
?>

<?php if ( $nova_consulta->have_posts() ): ?>
    <?php while ( $nova_consulta->have_posts() ): ?>
        <?php $nova_consulta->the_post(); ?>
        <?php the_title();?><br>
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

Perceba que ao invés de chamar a função have_posts() e the_post() diretamente, agora eu as chamo diretamente do novo objeto que criei da classe WP_Query, com isso não afeto o conteúdo do loop principal.

Por exemplo, vamos pegar o loop principal que criei anteriormente, mais o código acima juntos:

<?php
$nova_consulta = new WP_Query( 
    array( 
        'post__in' => get_option('sticky_posts'),
    ) 
);
?>

<?php if ( $nova_consulta->have_posts() ): ?>
    <?php while ( $nova_consulta->have_posts() ): ?>
        <?php $nova_consulta->the_post(); ?>
        <?php the_title();?><br>
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

<?php if ( have_posts() ): ?> 
    <?php while ( have_posts() ) : the_post(); ?>
    
        <!-- As template tags virão abaixo -->
        <?php the_title();?><br>
        <?php the_content();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

Agora eu tenho dois loops dentro da mesma página; o primeiro exibe apenas os posts fixos (sticky); o segundo exibe o conteúdo padrão do site.

Um problema que você pode encontrar com isso, é que os posts fixos serão exibidos nas duas consultas. Para resolver o problema, você pode gerar um array, na primeira consulta, que receberá os IDs dos posts já exibidos. Na segunda consulta você só vai precisar conferir se o ID do post que será exibido não está naquele array.

Fica assim o código:

<?php
// Array que vai receber os posts que não quero repetir
$nao_repetir = array();

$nova_consulta = new WP_Query( 
    array( 
        'post__in' => get_option('sticky_posts'),
    ) 
);
?>

<?php if ( $nova_consulta->have_posts() ): ?>
    <?php while ( $nova_consulta->have_posts() ): ?>
    
        <?php $nova_consulta->the_post(); ?>
        
        <!-- Preenche o array -->
        <?php $nao_repetir[] = $post->ID; ?>
        
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

<br><br>

<?php if ( have_posts() ): ?> 
    <?php while ( have_posts() ) : the_post(); ?>
        
        <!-- Verifica o ID do post -->
        <?php if ( in_array( $post->ID, $nao_repetir ) ) continue; ?>

        <!-- As template tags virão abaixo -->
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

As partes importantes aqui são as seguintes:

<?php
...
$nao_repetir = array();
...
// Primeiro loop
<?php $nao_repetir[] = $post->ID; ?>
...
// Segundo loop
<?php if ( in_array( $post->ID, $nao_repetir ) ) continue; ?>

Ou seja: no primeiro loop preenchemos o array que contém os IDs dos posts que não queremos repetir; no segundo loop verificamos se o ID do post que será exibido está no array. Se estiver, a palavra chave continue fará com que o laço while pule para a próxima volta (para o próximo post) sem exibir nada.

Vamos incluir mais um loop, porém agora vamos exibir o seguinte:

  • Primeiro loop: Apenas posts fixos;
  • Segundo loop: Posts da categoria de ID 20;
  • Terceiro loop: Padrão (excluindo posts já exibidos);

Veja como fica:

<?php
$segunda_consulta = new WP_Query( 
    array( 
        'cat'            => 20, // Apenas posts da categoria 20 
        'posts_per_page' => 5,    // Apenas 5 posts
    ) 
);
?>

<?php if ( $segunda_consulta->have_posts() ): ?>
    <?php while ( $segunda_consulta->have_posts() ): ?>
    
        <?php $segunda_consulta->the_post(); ?>
        
        <!-- Preenche o array -->
        <?php $nao_repetir[] = $post->ID; ?>
        
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

Agora tudo junto:

<?php
// Array que vai receber os posts que não quero repetir
$nao_repetir = array();

$nova_consulta = new WP_Query( 
    array( 
        'post__in' => get_option('sticky_posts'),
    ) 
);
?>

<?php if ( $nova_consulta->have_posts() ): ?>
    <?php while ( $nova_consulta->have_posts() ): ?>
    
        <?php $nova_consulta->the_post(); ?>
        
        <!-- Preenche o array -->
        <?php $nao_repetir[] = $post->ID; ?>
        
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

<br><br>

<?php
$segunda_consulta = new WP_Query( 
    array( 
        'cat'            => '20', // Apenas posts da categoria 20 
        'posts_per_page' => 5,    // Apenas 5 posts
    ) 
);
?>

<?php if ( $segunda_consulta->have_posts() ): ?>
    <?php while ( $segunda_consulta->have_posts() ): ?>
    
        <?php $segunda_consulta->the_post(); ?>
        
        <!-- Preenche o array -->
        <?php $nao_repetir[] = $post->ID; ?>
        
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

<?php wp_reset_postdata(); ?>

<br><br>

<?php if ( have_posts() ): ?> 
    <?php while ( have_posts() ) : the_post(); ?>
        
        <!-- Verifica o ID do post -->
        <?php if ( in_array( $post->ID, $nao_repetir ) ) continue; ?>

        <!-- As template tags virão abaixo -->
        <?php the_title();?><br>
        
    <?php endwhile; ?>
<?php endif; ?>

Sei que é bastante código e pode assustar, mas é bem simples.

Uma observação importante: Não se esqueça de utilizar wp_reset_postdata() para restaurar a variável global $post após cada loop secundário.

Concluindo

Trabalhar com vários loops no WordPress não é complicado, porém, exige que você tenha noção de programação. Eles irão aumentar o número de consultas na base de dados, e, se não criados com perfeição, podem atrapalhar o loop principal, que é de onde vem o seu ganha pão.

O WordPress codex está cheio de exemplos e dicas, não deixe de conferir.

Em caso de dúvidas, não hesite em comentar!