Como dividir um loop em várias colunas

11

Se eu tiver um loop em execução em uma consulta de categoria como:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<ul>
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<li>.. </li><?php wp_reset_query(); ?>
<?php endwhile; ?>
</ul>

Como eu criaria uma cláusula if que quebra a lista em um determinado intervalo e inicia uma nova. Por exemplo, no 10º post, retorne um </ul> e inicie um novo <ul> em 11.

Isso está incorreto, mas para ilustrar meu objetivo:

<?php $count =0;
    while($count <=50){
        if ($count == 9){
            echo "<li><a href='<?php the_permalink(); ?>'>
                      <?php the_title(); ?></a></li></ul>";
            } 
        elseif ($count == 10){
        echo "<ul><li><a href='<?php the_permalink(); ?>'>
                          <?php the_title(); ?></a></li>";
        }
        else {
        echo "<li><a href='<?php the_permalink(); ?>'><?php the_title(); ?></a></li>";
        }

Qual é a maneira correta de incluir essa lógica no loop?

    
por zac 14.02.2011 / 12:58

5 respostas

21

Crie colunas para sua consulta e exibição fácil

Nos temas, provavelmente é mais útil ter algo que se encaixe bem nas tags de modelo e no loop. Minha primeira resposta não se concentrou muito nisso. Além disso, achei que era complicado demais para uma adoção rápida.

Uma abordagem mais fácil que surgiu em minha mente foi estender "o loop" com colunas e chegou a esta solução até agora:

Um objeto WP_Query_Columns "estende" qualquer consulta padrão do WP com colunas que possam ser facilmente iteradas. O primeiro parâmetro é a variável de consulta e o segundo parâmetro é o número de itens a serem exibidos por coluna:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<?php foreach(new WP_Query_Columns($the_query, 10) as $column_count) : ?>
    <ul>
        <?php while ($column_count--) : $the_query->the_post(); ?>
        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php endwhile; ?>
    </ul>
<?php endforeach; ?>

Para usá-lo, basta adicionar a classe WP_Query_Columns desta essência aos seus temas function.php.

Uso avançado

Se você precisar do número da coluna que está exibindo no momento (por exemplo, para algumas classes CSS pares / ímpares, também é possível obter isso do foreach:

<?php foreach(new WP_Query_Columns($the_query, 10) as $column => $column_count) : ?>

E o número total de colunas também está disponível:

<?php 
    $the_columns = new WP_Query_Columns($the_query, 10);
    foreach($the_columns as $column => $column_count) : 
?>
    <h2>Column <?php echo $column; ?>/<?php echo sizeof($the_columns); ?></h2>
    <ul>...

Vinte e dez exemplos

Eu poderia hackear rapidamente vinte e dez temas para um teste e adicionar manchetes acima de qualquer loop dessa maneira. É inserido em loop.php, o começo é o código do tema:

<?php /* If there are no posts to display, such as an empty archive page */ ?>
<?php if ( ! have_posts() ) : ?>
    <div id="post-0" class="post error404 not-found">
        <h1 class="entry-title"><?php _e( 'Not Found', 'twentyten' ); ?></h1>
        <div class="entry-content">
            <p><?php _e( 'Apologies, but no results were found for the requested archive. Perhaps searching will help find a related post.', 'twentyten' ); ?></p>
            <?php get_search_form(); ?>
        </div><!-- .entry-content -->
    </div><!-- #post-0 -->
<?php endif; ?>

<!-- WP_Query_Columns -->
<?php 
    ### Needs WP_Query_Columns --- see http://wordpress.stackexchange.com/q/9308/178
    $query_copy = clone $wp_query; // save to restore later
    foreach( new WP_Query_Columns($wp_query, 3) as $columns_index => $column_count ) : ?>
    <ul>
        <?php 
        while ( $column_count-- ) : the_post(); ?>
            <li><h2 class="entry-title"><a href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'twentyten' ), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php the_title(); ?></a></h2></li>
        <?php endwhile; ?>
    </ul>       
<?php endforeach; ?>
<?php $wp_query = $query_copy;?>

<?php
    /* Start the Loop.
    ...

Para uma resposta mais longa:

(isso é basicamente como cheguei ao material acima, mas explica melhor como realmente resolver o problema com operações matemáticas simples. Minha nova solução é fazer uma iteração sobre algo pré-calculado).

Depende um pouco de quanto você realmente precisa para resolver o problema.

Por exemplo, se o número de itens por coluna for igual a um, isso é muito simples:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>    
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<ul>
    <li>.. </li>
<ul>
<?php endwhile;  wp_reset_query(); ?>
</ul>

Mesmo com esse código simples, pode-se ver que há várias decisões a serem tomadas:

  • Quantos itens estão em uma coluna?
  • Quantos itens existem no total?
  • Existe uma nova coluna para começar?
  • E há uma coluna para terminar?

A última pergunta é interessante para a saída em HTML, já que você provavelmente deseja incluir não apenas itens, mas também a coluna com elementos html.

Felizmente, com o código, podemos definir tudo isso em variáveis e criar códigos que sempre computam para as nossas necessidades.

E, às vezes, nem podemos responder a todas as perguntas desde o começo. Por exemplo, a contagem do total de itens: há algum, vários, vários, uma contagem exata que corresponde a um número inteiro de colunas no total?

Mesmo a resposta de Jan Fabry pode funcionar em alguns casos (como o exemplo acima faz para o cenário de um item por coluna), você pode estar interessado em algo que funcione para qualquer número de itens retornados por WP_Query.

Primeiro para a matemática:

//
// arithmetical example:
//
# configuration:
$colSize = 20;  // number of items in a column
$itemsTotal = 50; // number of items (total)

# calculation:
$count = 0; // a zero-based counter variable
$isStartOfNewColum = 0 === ($count % $colSize); // modulo operation
$isEndOfColumn = ($count && $isStartOfNewColum) || $count === $itemsTotal; // encapsulation

Esse código não roda, então vamos colocar isso em um simples exemplo de texto

//
// simple-text example:
//
$column = 0; // init a column counter
for($count=0; $count<= $itemsTotal; $count++) {
    $isStartOfNewColum = 0 === ($count % $colSize); // modulo
    $isEndOfColumn = ($count && $isStartOfNewColum);
    $isStartOfNewColum && $column++; // update column counter

    if ($isEndOfColumn) {
        printf("/End of Column: %d\n", $column-1);
    }

    if ($isStartOfNewColum) {
        printf("<start of Column: %d\n", $column);
    }

    printf(" * item %d\n", $count);
}
if ($count && !$isEndOfColumn && --$count === $itemsTotal) {
    printf("/End of Column: %d\n", $column);
}

printf("Done. Total Number of Columns: %d.\n", $column);

Isso realmente é executado e já produz alguma saída:

<start of Column: 1
 * item 0
 * item 1
 * item 2
 * item 3
...
 * item 17
 * item 18
 * item 19
/End of Column: 1
<start of Column: 2
 * item 20
 * item 21
 * item 22
...
 * item 37
 * item 38
 * item 39
/End of Column: 2
<start of Column: 3
 * item 40
 * item 41
 * item 42
...
 * item 48
 * item 49
 * item 50
/End of Column: 3
Done. Total Number of Columns: 3.

Isso já simula muito bem como poderia parecer em um modelo de wordpress:

//
// wordpress example:
//
$count = 0; // init item counter
$column = 0; // init column counter
$colSize = 10; // column size of ten this time
$the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');
$itemsTotal = $the_query->post_count;
?>
<?php while ($the_query->have_posts()) : $the_query->the_post();?>
<?php
    # columns display variables 
    $isStartOfNewColum = 0 === ($count % $colSize); // modulo
    $isEndOfColumn = ($count && $isStartOfNewColum);
    $isStartOfNewColum && $column++; // update column counter

    if ($isEndOfColumn) {
        print('</ul>');
    }

    if ($isStartOfNewColum) {
        printf('<ul class="col-%d">', $column);
    }
?>
    <li> ... make your day ...
    </li>
<?php endwhile; ?>
<?php
if ($count && !$isEndOfColumn && --$count === $itemsTotal) {
    print('</ul>');
}
// You don't have to do this in every loop, just once at the end should be enough
wp_reset_query();
?>

(Eu não executei o último exemplo em um ambiente WP, mas deve estar pelo menos sintaticamente correto.)

    
por hakre 14.02.2011 / 14:03
2

Esta é mais uma questão geral de programação, mas aqui está a ideia básica:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<ul>
<?php
$post_counter = 0;
while ($the_query->have_posts()) :
    $the_query->the_post();
    $post_counter++;
?>
    <li>.. </li>
<?php
    if ( 0 == $post_counter % 10 ) {
        echo '</ul><ul>';
    }
endwhile;
?>
</ul>
<?php
// You don't have to do this in every loop, just once at the end should be enough
wp_reset_query();
?>
    
por Jan Fabry 14.02.2011 / 13:06
1

Não é necessário criar um var separado para contagem, pois a consulta var já conta em: $wp_query->current_post . Além disso, é necessário contabilizar a entrada final na lista para que você não tenha o <ul></ul> vazio na sua marcação.

<?php 
$the_query = new WP_Query('showposts=21&orderby=title&order=asc'); 
echo "<ul>";
while ($the_query->have_posts()) :
    $the_query->the_post();
    echo "<li>{$the_query->current_post}</li>";

    // Note that the post is already counted in the $the_query->current_post variable when in the loop. Add one to translate array counting to real counts.
    // Jan's example didn't account for the final entry in the list. Don't want empty <ul>'s hanging around
    if ((($the_query->current_post+1) % 10 == 0) && ($the_query->current_post+1 !== count($the_query->posts))):
        echo "</ul><ul>";
    endif;
endwhile;
echo "</ul>";
?>
    
por Dan Gayle 14.02.2011 / 20:41
0

Adicione a função get_columns_array() ao seu function.php. Você pode então facilmente iterar nas suas colunas:

No seu tema, você então encara o loop sobre as colunas:

<?php $the_query = new WP_Query('cat=1&showposts=50&orderby=title&order=asc');?>
<?php foreach(get_columns_array($post_count) as $column_count) : ?>
    <ul>
        <?php while ($column_count--) : $the_query->the_post(); ?>
        <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
        <?php endwhile; ?>
    </ul>
<?php endforeach; wp_reset_postdata(); ?>

Defino o tamanho padrão de uma coluna como 10. Você pode usar o segundo parâmetro para definir o tamanho de uma coluna sozinho. Gostaria de 7: get_columns_array($post_count, 7); .

    
por hakre 14.02.2011 / 19:15
0

Aqui está outra abordagem que você pode seguir:

$article = 0;

<?php if (have_posts()) : ?>
    <?php while (have_posts()) : the_post(); ?>
        <?php $article = $article + 1; ?>
        <?php if ($article % 3 == 1) echo '<div class="row-fluid">';  ?>
            <div class="span4">
            <h2><a href="<?php esc_url( the_permalink() ); ?>" title="Permalink to <?php the_title(); ?>" rel="bookmark"><?php the_title(); ?></a></h2>
            </div><!--/span-->
        <?php if ($article % 3 == 0) echo '</div><!--/row-->';  ?>
    <?php endwhile;?>
<?php else: ?>
<h2>...</h2>
<?php endif; ?>
    
por Vincent 11.09.2012 / 19:33

Tags