Cómo dividir un bucle en varias columnas

11

Si tengo un bucle que se ejecuta desde una consulta de categoría 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>

¿Cómo crearía una cláusula if que rompa la lista en un cierto intervalo e inicie una nueva? Así, por ejemplo, en la décima publicación, devuelva un </ul> y comience un nuevo <ul> en 11.

Esto es incorrecto, pero para ilustrar mi 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>";
        }

¿Cuál es la forma correcta de incluir esta lógica en el bucle?

    
pregunta zac 14.02.2011 - 12:58

5 respuestas

21

Crea columnas para tu consulta y muestra fácilmente

En los temas es probablemente más útil tener algo que se ajuste bien a las etiquetas de plantilla y al bucle. Mi primera respuesta no se centró mucho en eso. Además, pensé que es un poco complicado para una rápida adopción.

Un enfoque más fácil que me vino a la mente fue extender "el bucle" con columnas y llegar a esta solución hasta ahora:

Un objeto WP_Query_Columns "extiende" cualquier consulta WP estándar con columnas que se puedan iterar fácilmente. El primer parámetro es la variable de consulta y el segundo parámetro es el número de elementos que se mostrarán por columna:

<?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 usarlo, simplemente agregue la clase WP_Query_Columns desde este gist a su función de temas.php.

Uso avanzado

Si necesita el número de columna que está mostrando actualmente (por ejemplo, para algunas clases de CSS pares / impares, también puede obtenerlo en el foreach:

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

Y el número total de columnas también está disponible:

<?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>...

Ejemplo de Twenty Ten

Podría hackear rápidamente el tema de veinte diez para una prueba y agregar titulares sobre cualquier bucle de esta manera. Se inserta en loop.php, el principio es el código del 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 una respuesta más larga:

(así es básicamente como llegué a las cosas anteriores, pero explica mejor cómo resolver realmente el problema con operaciones matemáticas simples. Mi nueva solución es iterar sobre algo pre-calculado).

Depende un poco de cuánto necesites para resolver el problema.

Por ejemplo, si el número de elementos por columna es igual a uno, esto es muy simple:

<?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>

Incluso con ese código simple, se puede ver que hay varias decisiones que deben tomarse:

  • ¿Cuántos elementos hay en una columna?
  • ¿Cuántos artículos hay en total?
  • ¿Hay una nueva columna para comenzar?
  • ¿Y hay una columna para terminar?

La última pregunta es bastante interesante para la salida HTML, ya que es probable que desee incluir no solo los elementos, sino también la columna con los elementos html.

Afortunadamente con el código, podemos configurar todas estas variables y crear un código que siempre se adapte a nuestras necesidades.

Y a veces incluso, ni siquiera podemos responder a todas las preguntas desde el principio. Por ejemplo, el recuento del total de elementos: ¿Hay alguno, algunos, múltiple, un recuento exacto que coincida con un número entero de columnas en total?

Incluso la respuesta de Jan Fabry podría funcionar en algunos casos (como lo hace mi ejemplo anterior para el escenario de un elemento por columna), podría interesarle algo que funcione para cualquier número de elementos devueltos por WP_Query.

Primero para las matemáticas:

//
// 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

El código no se ejecuta, así que vamos a incluirlo en un ejemplo de texto simple

//
// 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);

Esto realmente se ejecuta y ya produce algo de salida:

<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.

Esto simula ya bastante bien cómo podría verse en una plantilla 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();
?>

(No he ejecutado el último ejemplo en un entorno WP, pero debería ser al menos sintácticamente correcto)

    
respondido por el hakre 14.02.2011 - 14:03
2

Esta es más una pregunta de programación general, pero aquí está la idea 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();
?>
    
respondido por el Jan Fabry 14.02.2011 - 13:06
1

No es necesario crear una var para el conteo, ya que la var de la consulta ya cuenta en: $wp_query->current_post . Además, debe tener en cuenta la entrada final en la lista para que no tenga <ul></ul> vacío en su marca.

<?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>";
?>
    
respondido por el Dan Gayle 14.02.2011 - 20:41
0

Agregue la función get_columns_array() a su function.php. Luego puede iterar fácilmente sobre sus columnas:

En tu tema, a continuación, foreach bucle sobre las columnas:

<?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(); ?>

Establecí el tamaño predeterminado de una columna en 10. Puedes usar el segundo parámetro para establecer el tamaño de una columna por tu cuenta. Me gusta a 7: get_columns_array($post_count, 7); .

    
respondido por el hakre 14.02.2011 - 19:15
0

Este es otro enfoque que puede tomar:

$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; ?>
    
respondido por el Vincent 11.09.2012 - 19:33

Lea otras preguntas en las etiquetas