Jak podzielić pętlę na wiele kolumn

11

Jeśli mam pętlę uruchomioną z zapytania kategorii, takiego jak:

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

Jak utworzę klauzulę if, która łamie listę w określonym przedziale czasowym i uruchamia nową. Na przykład na 10. postu zwróć a </ul>i rozpocznij nowy <ul>o 11.

Jest to nieprawidłowe, ale dla zilustrowania mojego celu:

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

Jaki jest prawidłowy sposób włączenia tej logiki do pętli?

zac
źródło
Zaktualizowałem odpowiedź o coś, co powinno być ogólnie łatwe w użyciu i przetestowane.
hakre

Odpowiedzi:

21

Utwórz kolumny dla swojego zapytania i łatwego wyświetlania

W motywach prawdopodobnie bardziej przydatne jest posiadanie czegoś, co dobrze pasuje do tagów szablonów i pętli. Moja pierwsza odpowiedź nie koncentrowała się tak bardzo. Dodatkowo pomyślałem, że jest to zbyt skomplikowane, aby można je było szybko adoptować.

Łatwiejszym podejściem, które przyszło mi do głowy, było rozszerzenie „pętli” o kolumny i do tej pory doszło do tego rozwiązania:

Obiekt WP_Query_Columns „rozszerza” każde standardowe zapytanie WP za pomocą kolumn, które można łatwo iterować. Pierwszy parametr to zmienna zapytania, a drugi parametr to liczba elementów do wyświetlenia w kolumnie:

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

Aby go użyć, po prostu dodaj klasę WP_Query_Columns z tej listy do swojego motywu function.php.

Zaawansowane użycie

Jeśli potrzebujesz numeru kolumny, który aktualnie wyświetlasz (np. W przypadku niektórych parzystych / nieparzystych klas CSS, możesz go również uzyskać z foreach:

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

Dostępna jest także całkowita liczba kolumn:

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

Dwadzieścia dziesięć przykładów

Mogę szybko zhakować dwadzieścia dziesięć motywów na test i w ten sposób dodać nagłówki ponad dowolną pętlę. Jest wstawiony do loop.php, początkiem jest kod motywu:

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

Aby uzyskać dłuższą odpowiedź:

(tak po prostu doszedłem do powyższych rzeczy, ale lepiej wyjaśnia, jak rozwiązać problem za pomocą prostych operacji matematycznych. Moim nowym rozwiązaniem jest iteracja czegoś wstępnie obliczonego).

To trochę zależy od tego, ile naprawdę potrzebujesz, aby rozwiązać problem.

Na przykład, jeśli liczba elementów w kolumnie jest równa jeden, jest to bardzo proste:

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

Nawet przy tym prostym kodzie widać, że należy podjąć wiele decyzji:

  • Ile przedmiotów jest w jednej kolumnie?
  • Ile jest w sumie przedmiotów?
  • Czy jest nowa kolumna na początek?
  • I czy jest kolumna do końca?

Ostatnie pytanie jest dość interesujące dla danych wyjściowych HTML, ponieważ prawdopodobnie chcesz zawrzeć nie tylko elementy, ale także kolumnę z elementami HTML.

Na szczęście dzięki kodowi możemy ustawić wszystkie te zmienne i stworzyć kod, który zawsze będzie obliczał nasze potrzeby.

A czasem nawet nie jesteśmy w stanie odpowiedzieć na każde pytanie od samego początku. Na przykład, liczba wszystkich elementów: czy istnieje jakaś, kilka, wiele dokładnych liczb, które pasują do całkowitej liczby kolumn w sumie?

Nawet odpowiedź Jana Fabry'ego może działać w niektórych przypadkach (tak jak mój przykład powyżej dla scenariusza z jedną pozycją na kolumnę), możesz być zainteresowany czymś, co działa na dowolną liczbę elementów zwróconych przez WP_Query.

Najpierw matematyka:

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

Ten kod nie działa, więc postawmy to w prostym przykładzie tekstowym

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

To faktycznie działa i wykonuje już pewne dane wyjściowe:

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

Symuluje to już całkiem dobrze, jak mogłoby to wyglądać w szablonie 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();
?>

(Nie wykonałem ostatniego przykładu w środowisku WP, ale powinien on być co najmniej poprawny pod względem składniowym).

hakre
źródło
2

Jest to bardziej ogólne pytanie dotyczące programowania, ale oto podstawowa idea:

<?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
źródło
Działanie modulo jest w zasadzie matematyczną odpowiedzią. Ale twój przykład nie ma semantycznego wyniku HTML. W mojej odpowiedzi zaproponowałem coś podobnego, ponieważ można sobie wyobrazić, że zajęło to trochę więcej czasu;)
hakre
wp_reset_query();nie jest powiązany ze zmienną $ the_query. To wcale nie jest potrzebne, prawda?
hakre
@hakre: $the_query->the_post()nadpisze $postzmienną globalną i wp_reset_query()przywraca ją (wywołując wp_reset_postdata()- co samo może być wystarczające?).
Jan Fabry
Ok, jakoś zmiksowałem wp_query i napisałem trochę, myślałem, że to coś zrobi, $wp_queryale $the_queryzostało użyte w tym przykładzie. Jednak się myliłem, dodam to do mojej drugiej odpowiedzi w celu uzupełnienia.
hakre
Nie rozliczasz ostatniej pozycji. Jeśli pętla zakończy się liczbą podzielną przez 10, otrzymasz pusty zestaw <ul></ul>.
Dan Gayle
1

Nie ma potrzeby tworzenia oddzielnej var do liczenia, ponieważ var query już liczy się go pod adresem: $wp_query->current_post. Ponadto należy uwzględnić ostatni wpis na liście, aby nie było pustych <ul></ul>znaczników.

<?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
źródło
Odnotowany. Dodano przykład.
Dan Gayle
Fajnie, podoba mi się ten dodatek, ponieważ pusty ´ <ul> </ul> `jest teraz tylko dla 0 postów (ale dla tych nadal jest) - ale z tego, czego się dzisiaj nauczyłem, ta forma jest najmniejsza z / o wprowadzenie nowej funkcji.
hakre
Miły dodatek. Widzę, że WP_Queryma również $post_countzmienną, której możesz użyć zamiast count($the_query->posts). Zac, możesz „nie zaakceptować” mojej odpowiedzi i zaakceptować inną, jeśli to lepiej rozwiąże twój problem.
Jan Fabry
@Jan - Wolę zmienną kapsułkowaną niż zmienną globalną, ponieważ zwiększa to modułowość. Ale dobrze wiedzieć, że jest jeden.
hakre
0

Dodaj get_columns_array()funkcję do swojego function.php. Następnie możesz łatwo iterować po kolumnach:

W swoim motywie przewidujesz następnie pętlę nad kolumnami:

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

Ustawiam domyślny rozmiar kolumny na 10. Możesz użyć drugiego parametru, aby ustawić rozmiar kolumny na własną rękę. Lubią 7: get_columns_array($post_count, 7);.

hakre
źródło
0

Oto inne podejście, które możesz zastosować:

$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
źródło