web-dev-qa-db-fra.com

Comment diviser une boucle en plusieurs colonnes

Si j'ai une boucle en cours d'exécution à partir d'une requête de catégorie comme:

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

Comment pourrais-je créer une clause if qui coupe la liste à un certain intervalle et en crée une nouvelle. Ainsi, par exemple, à la 10ème mission, renvoyez un </ul> et démarrez-en un nouveau <ul> à 11.

Ceci est incorrect mais pour illustrer mon objectif:

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

Quelle est la bonne façon d'inclure cette logique dans la boucle?

11
zac

Créez des colonnes pour votre requête et un affichage facile

Dans les thèmes, il est probablement plus utile d’avoir quelque chose qui s’intègre bien dans les balises de gabarit et la boucle. Ma première réponse ne s'est pas concentrée sur cela. De plus, j'ai pensé que c'était un peu trop compliqué pour une adoption rapide.

Une approche plus facile qui m'est venue à l'esprit consistait à étendre "la boucle"} avec des colonnes et a abouti à cette solution jusqu'à présent:

A WP_Query_Columns object "étend" toute requête WP standard avec des colonnes pouvant être facilement itérées. Le premier paramètre est la variable de requête et le second paramètre est le nombre d'éléments à afficher par colonne:

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

Pour l'utiliser, ajoutez simplement la classe WP_Query_Columns de ce Gist à votre thème function.php.

Utilisation avancée

Si vous avez besoin du numéro de colonne que vous affichez actuellement (par exemple, pour certaines classes CSS paires/impaires, vous pouvez également l'obtenir auprès de foreach:

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

Et le nombre total de colonnes est également 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>...

Exemple Vingt Dix

Je pourrais rapidement pirater vingt-dix thèmes pour un test et ajouter des titres au-dessus de toute boucle de cette façon. C'est inséré dans loop.php, le début est le code du thème:

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

Pour une réponse plus longue:

(c’est en gros ce qui m’a amené à ce qui précède, mais explique mieux comment résoudre le problème à l’aide d’opérations mathématiques simples. Ma nouvelle solution consiste à itérer sur quelque chose de pré-calculé.)}

Cela dépend un peu de ce dont vous avez réellement besoin pour résoudre le problème.

Par exemple, si le nombre d'éléments par colonne est égal à un, la procédure est très 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>

Même avec ce code simple, on peut voir qu'il y a plusieurs décisions à prendre:

  • Combien d'éléments sont dans une colonne?
  • Combien d'articles y a-t-il au total?
  • Y a-t-il une nouvelle colonne pour commencer?
  • Et y a-t-il une colonne à terminer?

La dernière question est assez intéressante pour la sortie HTML car vous souhaitez probablement inclure non seulement des éléments mais également la colonne avec des éléments html.

Heureusement, avec le code, nous pouvons définir toutes ces variables et créer un code toujours adapté à nos besoins.

Et parfois même, on ne peut même pas répondre à toutes les questions du début. Par exemple, le nombre total d'éléments: existe-t-il des nombres exacts, multiples, qui correspondent à un nombre entier de colonnes?

Même la réponse de Jan Fabry peut fonctionner dans certains cas (comme le montre l'exemple ci-dessus pour le scénario à un élément par colonne), vous pourriez être intéressé par quelque chose qui fonctionne pour n'importe quel nombre d'éléments renvoyés par WP_Query.

D'abord pour le calcul:

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

Ce code ne fonctionne pas, alors mettons cela dans un exemple de texte 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);

Cela fonctionne et fait déjà quelques sorties:

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

Cela simule déjà assez bien à quoi ça ressemble pourrait dans un modèle 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();
?>

(Je n'ai pas exécuté le dernier exemple dans un environnement WP, mais il devrait être au moins syntaxiquement correct.)

21
hakre

C'est plus une question de programmation générale, mais voici l'idée de 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();
?>
2
Jan Fabry

Il n'est pas nécessaire de créer une variable distincte pour le comptage, car la variable var la compte déjà à: $wp_query->current_post. En outre, vous devez rendre compte de la dernière entrée de la liste pour ne pas avoir <ul></ul> vide dans votre balisage.

<?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>";
?>
1
Dan Gayle

Voici une autre approche que vous pouvez adopter:

$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; ?>
0
Vincent

Ajoutez la fonction get_columns_array() à votre function.php. Vous pouvez alors facilement parcourir vos colonnes:

Dans votre thème, vous devez ensuite passer en boucle sur les colonnes:

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

J'ai défini la taille par défaut d'une colonne sur 10. Vous pouvez utiliser le second paramètre pour définir vous-même la taille d'une colonne. Comme pour 7: get_columns_array($post_count, 7);.

0
hakre