Come dividere un loop in più colonne


11

Se ho un ciclo in esecuzione da una query di categoria come:

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

Come potrei creare una clausola if che interrompe l'elenco a un determinato intervallo e ne avvia uno nuovo. Quindi, ad esempio al decimo post, restituisci a </ul>e iniziane uno nuovo <ul>alle 11.

Questo non è corretto ma per illustrare il mio obiettivo:

<?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 è il modo corretto di includere questa logica nel loop?


Ho aggiornato la mia risposta con qualcosa che dovrebbe essere generalmente facile da usare e testato.
hakre,

Risposte:


21

Crea colonne per la tua query e una facile visualizzazione

Nei temi è probabilmente più utile avere qualcosa che si adatta bene ai tag modello e al ciclo. La mia prima risposta non si è concentrata così tanto. Inoltre, ho pensato che fosse un po 'troppo complicato per una rapida adozione.

Un approccio più semplice che mi è venuto in mente è stato quello di estendere "il ciclo" con le colonne e finora è arrivato a questa soluzione:

Un oggetto WP_Query_Columns "estende" qualsiasi query WP standard con colonne che possono essere facilmente ripetute. Il primo parametro è la variabile di query e il secondo parametro è il numero di elementi da visualizzare per colonna:

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

Per usarlo, aggiungi semplicemente la classe WP_Query_Columns da questa sintesi al tuo function.php.

Uso avanzato

Se hai bisogno del numero di colonna che stai visualizzando (ad esempio per alcune classi CSS pari / dispari, puoi ottenerlo anche dal foreach:

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

E anche il numero totale di colonne è disponibile:

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

Venti dieci esempi

Potrei rapidamente hackare il tema ventitre per un test e aggiungere titoli sopra qualsiasi ciclo in questo modo. È inserito in loop.php, l'inizio è il codice 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.
    ...

Per una risposta più lunga:

(questo è fondamentalmente il modo in cui sono arrivato alla roba sopra, ma spiega meglio come risolvere effettivamente il problema con semplici operazioni matematiche. La mia nuova soluzione è quella di iterare su qualcosa di pre-calcolato.)

Dipende un po 'da quanto è effettivamente necessario per risolvere il problema.

Ad esempio, se il numero di elementi per colonna è uguale a uno, questo è molto semplice:

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

Anche con quel semplice codice, si può vedere che ci sono più decisioni da prendere:

  • Quanti elementi ci sono in una colonna?
  • Quanti articoli ci sono in totale?
  • C'è una nuova colonna da iniziare?
  • E c'è una colonna da finire?

L'ultima domanda è piuttosto interessante per l'output HTML in quanto probabilmente si desidera racchiudere non solo gli elementi ma anche la colonna con elementi html.

Fortunatamente con il codice, possiamo impostare tutto ciò in variabili e creare codice che calcola sempre in base alle nostre esigenze.

E a volte anche, non possiamo nemmeno rispondere a tutte le domande dall'inizio. Per esempio, il conteggio degli elementi totali: esiste un conteggio multiplo esatto che corrisponde a un numero intero di colonne in totale?

Anche la risposta di Jan Fabry potrebbe funzionare in alcuni casi (come il mio esempio sopra fa per lo scenario di un articolo per colonna), potresti essere interessato a qualcosa che funziona per qualsiasi numero di articoli restituiti da WP_Query.

Primo per la matematica:

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

Quel codice non viene eseguito, quindi inseriamolo in un semplice esempio di testo

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

Questo effettivamente funziona e fa già qualche output:

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

Questo simula già abbastanza bene come potrebbe apparire in un modello di 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();
?>

(Non ho eseguito l'ultimo esempio in un ambiente WP, ma dovrebbe essere almeno sintatticamente corretto.)


2

Questa è più una domanda di programmazione generale, ma ecco l'idea di base:

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

L'operazione modulo è sostanzialmente la risposta matematica. Ma il tuo esempio non ha un output HTML semantico. Ho proposto qualcosa di simile nella mia risposta, come puoi immaginare ci sia voluto un po 'più di tempo;)
hakre

wp_reset_query();non è correlato alla variabile $ the_query. Questo non è affatto necessario, giusto?
Hacre,

@hakre: $the_query->the_post()sovrascriverà la $postvariabile globale e la wp_reset_query()ripristinerà (chiamando wp_reset_postdata()- che potrebbe anche essere sufficiente da sola?).
Jan Fabry,

Ok, in qualche modo ho mescolato wp_query e postato un po ', ho pensato che avrebbe fatto qualcosa $wp_queryma è $the_querystato usato nell'esempio. Tuttavia, ho sbagliato, lo aggiungerò alla mia seconda risposta per completezza.
Hacre,

Non stai tenendo conto dell'ultimo elemento. Se il ciclo termina con un numero divisibile per 10, otterrai un set vuoto di <ul></ul>.
Dan Gayle,

1

Non c'è bisogno di creare una var separata per il conteggio, come la query var conta già all'indirizzo: $wp_query->current_post. Inoltre, devi tenere conto della voce finale nell'elenco in modo da non avere vuoti <ul></ul>nel markup.

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

Notato. Esempio aggiunto.
Dan Gayle,

Bene, mi piace l'aggiunta perché il vuoto ´ <ul> </ul> `è solo per 0 post ora (ma per quelli che lo è ancora) - ma da quello che ho imparato oggi, quel modulo è il più piccolo w / o introduzione di una nuova funzione.
Hacre,

Bella aggiunta. Vedo che WP_Queryha anche una $post_countvariabile, puoi usarla al posto di count($the_query->posts). Zac, puoi "non accettare" la mia risposta e accettarne un'altra se risolve meglio il tuo problema.
Jan Fabry,

@Jan - Preferirei la variabile incapsulata rispetto a quella globale perché questo aumenta la modularità. Ma è bello sapere che ce n'è uno.
Hakre,

0

Aggiungi la get_columns_array()funzione al tuo function.php. È quindi possibile scorrere facilmente le colonne:

Nel tuo tema quindi foreach loop sopra le colonne:

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

Ho impostato la dimensione predefinita di una colonna su 10. È possibile utilizzare il secondo parametro per impostare autonomamente la dimensione di una colonna. Come per 7: get_columns_array($post_count, 7);.


0

Ecco un altro approccio che puoi adottare:

$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; ?>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.