Comment diviser une boucle en plusieurs colonnes

11

Si j'ai une boucle exécutée à 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 créer une clause if qui casse la liste à un certain intervalle et en démarre une nouvelle. Ainsi, par exemple, au 10e poste, retournez un </ul>et commencez un nouveau <ul>à 11.

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

zac
la source
J'ai mis à jour ma réponse avec quelque chose qui devrait être généralement facile à utiliser et testé.
hakre

Réponses:

21

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 modèle et la boucle. Ma première réponse ne s'est pas concentrée sur tant de choses. De plus, je pensais que c'était un peu trop compliqué pour une adoption rapide.

Une approche plus facile qui m'est venue à l' esprit était d'étendre "la boucle" avec des colonnes et est arrivée à cette solution jusqu'à présent:

Un objet WP_Query_Columns "étend" toute requête WP standard avec des colonnes qui peuvent ê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, il vous suffit d'ajouter la classe WP_Query_Columns de cet essentiel à vos thèmes 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>...

Vingt-dix exemple

Je pourrais rapidement pirater vingt-dix thèmes pour un test et ajouter des titres au-dessus de n'importe quelle boucle de cette façon. Il 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 essentiellement comme cela que je suis arrivé aux choses ci-dessus, mais explique mieux comment résoudre réellement le problème avec des opérations mathématiques simples. Ma nouvelle solution est d'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, c'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'articles 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 voulez probablement inclure non seulement des éléments mais aussi la colonne avec des éléments html.

Heureusement avec le code, nous pouvons définir tout cela dans des variables et créer du code qui calcule toujours selon nos besoins.

Et parfois même, nous ne pouvons même pas répondre à toutes les questions depuis le début. Par exemple, le nombre total d'éléments: y a-t-il, certains, plusieurs, un nombre exact qui correspond à un nombre entier de colonnes au total?

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

D'abord pour les mathématiques:

//
// 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 s'exécute pas, nous allons donc mettre 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à une sortie:

<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 cela pourrait ressembler 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.)

hakre
la source
2

Il s'agit plus d'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();
?>
Jan Fabry
la source
L'opération modulo est fondamentalement la réponse mathématique. Mais votre exemple manque de sortie HTML sémantique. J'ai proposé quelque chose de similaire dans ma réponse, comme vous pouvez l'imaginer, cela a pris plus de temps;)
hakre
wp_reset_query();n'est pas lié à la variable $ the_query. Ce n'est pas du tout nécessaire, non?
hakre
@hakre: $the_query->the_post()écrasera la $postvariable globale et la wp_reset_query()restaure (en appelant wp_reset_postdata()- ce qui pourrait également suffire à lui seul?).
Jan Fabry
D'accord, j'ai en quelque sorte mélangé wp_query et posté un peu, pensant que cela ferait quelque chose $wp_querymais a $the_queryété utilisé dans l'exemple. Cependant, j'avais tort, je vais l'ajouter à ma deuxième réponse pour être complet.
hakre
Vous ne tenez pas compte du dernier élément. Si la boucle se termine sur un nombre divisible par 10, vous obtiendrez un ensemble vide de <ul></ul>.
Dan Gayle
1

Il n'y a pas besoin de créer un var distinct pour le comptage, comme la requête var compte déjà à l' adresse: $wp_query->current_post. En outre, vous devez tenir compte de l'entrée finale dans la liste afin de ne pas avoir de vide <ul></ul>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>";
?>
Dan Gayle
la source
C'est noté. Exemple ajouté.
Dan Gayle
Cool, j'aime l'ajout parce que le vide "<ul> </ul>" est seulement pour 0 postes maintenant (mais pour ceux-ci il l'est toujours) - mais d'après ce que j'ai appris aujourd'hui, ce formulaire est le plus petit avec o introduire une nouvelle fonction.
hakre
Belle addition. Je vois qu'il a WP_Queryégalement une $post_countvariable, vous pouvez l'utiliser à la place de count($the_query->posts). Zac, vous pouvez "refuser" ma réponse et en accepter une autre si elle résout mieux votre problème.
Jan Fabry
@Jan - Je préférerais la variable encapsulée à la variable globale car cela augmente la modularité. Mais bon de savoir qu'il y en a un.
hakre
0

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

Dans votre thème, vous passez ensuite chaque 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 deuxième paramètre pour définir la taille d'une colonne par vous-même. Comme à 7: get_columns_array($post_count, 7);.

hakre
la source
0

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; ?>
Vincent
la source