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 intervalo determinado y comience una nueva? Entonces, por ejemplo, en la décima publicación, devuelve ay </ul>comienza una nueva <ul>a las 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?

zac
fuente
Actualicé mi respuesta con algo que generalmente debería ser fácil de usar y probar.
Hakre

Respuestas:

21

Cree columnas para su consulta y visualización fácil

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

Un enfoque más fácil que se me ocurrió 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 de esta esencia a sus temas function.php.

Uso avanzado

Si necesita el número de columna que está mostrando actualmente (por ejemplo, para algunas clases CSS pares / impares, también puede obtenerlo desde 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>...

Vigésimo ejemplo

Podría hackear rápidamente el tema de veinte diez para una prueba y agregar encabezados sobre cualquier bucle de esta manera. Se inserta en loop.php, el comienzo 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 realmente resolver el problema con operaciones matemáticas simples. Mi nueva solución es iterar sobre algo precalculado).

Depende un poco de cuánto necesites realmente 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 que tomar múltiples decisiones:

  • ¿Cuántos artículos 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 probablemente desee incluir no solo elementos sino también la columna con elementos html.

Afortunadamente con el código, podemos establecer todo esto en variables y crear código que siempre calcule según nuestras necesidades.

Y a veces incluso, ni siquiera podemos responder todas las preguntas desde el principio. Por ejemplo, el recuento del total de elementos: ¿hay alguno, algunos, múltiples, 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), es posible que le interese algo que funcione para cualquier cantidad 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

Ese código no se ejecuta, así que pongámoslo 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 algunos resultados:

<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 ya simula 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).

hakre
fuente
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();
?>
Jan Fabry
fuente
La operación de módulo es básicamente la respuesta matemática. Pero su ejemplo carece de salida HTML semántica. He propuesto algo similar en mi respuesta, como puedes imaginar, tomó más tiempo;)
hakre
wp_reset_query();no está relacionado con la variable $ the_query. Esto no es necesario en absoluto, ¿verdad?
Hakre
@hakre: $the_query->the_post()sobrescribirá la $postvariable global y la wp_reset_query()restaurará (llamando wp_reset_postdata(), ¿qué también podría ser suficiente por sí solo?).
Jan Fabry
Bien, de alguna manera mezclé wp_query y publiqué un poco, pensé que haría algo, $wp_querypero $the_queryse usó en el ejemplo. Sin embargo, me equivoqué, lo agregaré a mi segunda respuesta para completar.
Hakre
No estás contabilizando el último artículo. Si el ciclo termina en un número divisible por 10, obtendrá un conjunto vacío de <ul></ul>.
Dan Gayle
1

No hay necesidad de crear un var separada para contar, como la consulta var ya cuenta en: $wp_query->current_post. Además, debe tener en cuenta la entrada final en la lista para no tener vacíos <ul></ul>en su marcado.

<?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>";
?>
Dan Gayle
fuente
Célebre. Ejemplo agregado.
Dan Gayle
Genial, me gusta la adición porque el ´ <ul> </ul> `vacío es solo para 0 publicaciones ahora (pero para las que aún lo es), pero de lo que he aprendido hoy, esa forma es la más pequeña con o introducir una nueva función.
Hakre
Buena adición. Veo que WP_Querytambién tiene una $post_countvariable, puede usar eso en lugar de count($the_query->posts). Zac, puedes "no aceptar" mi respuesta y aceptar otra si resuelve mejor tu problema.
Jan Fabry
@ Jan: preferiría la variable encapsulada sobre la global porque esto aumenta la modularidad. Pero es bueno saber que hay uno.
Hakre
0

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

Luego, en su tema, cada foreach recorre 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(); ?>

Establezco el tamaño predeterminado de una columna en 10. Puede usar el segundo parámetro para establecer el tamaño de una columna por su cuenta. Al igual que para el 7: get_columns_array($post_count, 7);.

hakre
fuente
0

Aquí hay 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; ?>
Vincent
fuente