Цикл внутри цикла?

6 нояб. 2012 г., 16:14:09
Просмотры: 38.9K
Голосов: 7

Я использую несколько пользовательских циклов wp_query на своей странице, первый получает новости из определенной категории и отображает небольшой отрывок из них со ссылкой.

Второй - это еще один wp_query, который получает пользовательский тип записи с несколькими дополнительными пользовательскими полями.

Проблема в том, что я хотел бы создать еще один цикл внутри второго, который получает 3 записи из раздела новостей с миниатюрами (по сути, противоположность первому циклу, он будет получать все остальные категории). После прочтения множества статей о цикле я не могу понять, как сделать "вложенный" цикл внутри моего второго цикла. Я уверен, что это должно быть просто, кажется чем-то легким в реализации.

Вот мой код с удаленной большей частью HTML.

<?php 
/*
*  Название шаблона: Главная страница
*/
?>

<?php get_header(); ?>

<div class="thenews">

    <div class="newsinner">

        <div class="grid-1">
            <h6 class="nsix">последние новости</h6>
        </div> <!-- конец div grid-1 -->

        <div class="grid-2">
            <?php
            $recentPosts = new WP_Query();
            $recentPosts->query('cat=5&showposts=1');
            ?>
            <?php while ($recentPosts->have_posts()) : $recentPosts->the_post(); ?>
            <p><?php echo ''.get_the_twitter_excerpt(); ?>...</p>
        </div> <!-- конец div grid-2 -->   

        <div class="grid-3">
            <a href="<?php the_permalink() ?>">Читать</a>
            <?php endwhile; wp_reset_query(); ?>
        </div> <!-- конец div grid-3 -->

    </div> <!-- конец div newsinner -->

</div> <!-- конец div thenews -->

<div id="main-content">

    <div class="typograhpy">

        <div class="home-grid-1">

            <div class="home-grid-1-inner">
                 <?php
                 $portfolio_query = new WP_Query(array(
                    'post_type' => 'headerhome',
                    'showposts' => 1
                ) );
                ?>
                <?php while ($portfolio_query->have_posts()) : $portfolio_query->the_post(); ?>
                <h2><?php the_title(); ?></h2>  
                <?php the_content(); ?>

                <div class="anyres">
                    <p> <?php the_field('anyresolution'); ?></p>
                </div> <!-- конец div anyres -->

            </div> <!-- конец home-gird-1-inner -->

        </div> <!-- конец home-grid-1 -->

        <div class="home-grid-2">

            <div class="inner-home-1">
                <div class="inside-home-1-1">
                 <h2><?php the_field('services_'); ?></h2>
                 <p> <?php the_field('services_text'); ?></p>
                </div> <!-- конец div inside-home-1-1 -->
                <div class="inside-home-1-2">
                    <p> <?php the_field('services_text_right'); ?></p>
                </div> <!-- конец div inside-home-1-2 -->
            </div> <!-- конец div inner-home-1 -->

            <div class="margindiv"></div>

            <div class="inner-home-2">
                <div class="brushpic"></div> <!-- конец div brushpic -->
                <h3><?php the_field('services_1_header') ?></h3>       
                <p><?php the_field('services_1_content'); ?></p>
            </div><!-- конец div inner-home-2 -->

            <div class="inner-home-3">
                <div class="cloudpic"></div> <!-- конец div cloudpic -->
                <h3><?php the_field('services_2_header') ?></h3>       
                <p><?php the_field('services_2_content'); ?></p>
            </div> <!-- конец div inner-home-3 -->

            <div class="inner-home-4">
                <div class="onetwoone"></div> <!-- конец div onetwoone -->
                <h3><?php the_field('services_3_header') ?></h3>       
                <p><?php the_field('services_3_content'); ?></p>
            </div> <!-- конец div inner-home-4 -->

        </div> <!-- конец div home-grid-2 -->

        <div style="clear:both"></div>

    </div> <!-- конец div typograhpy -->

    <div class="graphgrid">
    </div> <!-- конец div graphgrid -->

    <div class="sizesdes">                
        <blockquote><?php the_field('gallery_blockquote_') ?></blockquote>     
        <p><?php the_field('gallery_content'); ?></p>
        <?php endwhile; wp_reset_query(); ?>
    </div> 

</div><!-- конец div main-content -->
<?php get_footer(); ?>

Рабочий код, хотя он не получает the_post_thumbnail

<?php
// Сохраняем глобальную переменную post
global $post;$backup=$post;
$inner_query = new WP_Query();
$inner_query->query('showposts=3');
?>

<?php while ($inner_query->have_posts()) : $inner_query->the_post(); $post=$backup; ?>

    <?php the_post_thumbnail(); ?>

    <p><?php echo ''.get_the_custom_excerpt(); ?>...</p>

    <a href="<?php the_permalink() ?>">Читать</a>

<?php endwhile; ?>
1
Комментарии

Сделайте то же самое. Создайте новую переменную внутри второго цикла while и используйте $that_query->has_posts() и ->the_post(), но убедитесь, что вы не используете никакие данные из второго цикла после начала третьего. Также не забудьте использовать wp_query_reset() после вашего цикла while.

Eric Holmes Eric Holmes
6 нояб. 2012 г. 16:17:25
Все ответы на вопрос 3
8
19

Вы можете создать любое количество циклов, создавая дополнительные объекты WP_Query

$query = new WP_Query($args);

while ($query->have_posts()) :

    // инициализация $inner_args и сохранение текущего глобального $post
    $inner_query = new WP_Query($inner_args);

    while ($inner_query->have_posts()) :
        // выполняем какие-то действия
    endwhile;
    // восстанавливаем глобальный $post из ранее сохранённой резервной копии

endwhile;

ОБЪЯСНЕНИЕ, КАК ЗАПРОШЕНО

Когда вы вызываете шаблонный тег, например the_title();, он отображает что-то о текущей записи в цикле. Но как он узнаёт, какая запись является текущей? Это происходит путём чтения информации из глобальных данных записи (хранящихся в глобальной переменной $post)

При использовании цикла вы всегда используете $query->the_post() в качестве первого оператора. Эта функция устанавливает глобальные данные для следующей записи из объекта WP_Query (предыдущие данные при этом теряются)

В данном случае, когда вы вызываете внутренний цикл, данные записи внешнего цикла терялись, когда начинал работать внутренний цикл. Затем любые функции, которые вы используете после завершения внутреннего цикла, продолжали видеть только данные внутреннего цикла.

В решении вы сначала сохраняете данные внешнего цикла в другой переменной, прежде чем они будут потеряны. Затем цикл работает так, как должен (удаляя все данные внешнего цикла).

Когда работа внутреннего цикла завершена, вам нужно использовать данные внешнего цикла, но они уже потеряны из-за внутреннего цикла. Здесь вы берёте ранее сохранённые данные и заменяете ими текущие. Теперь вы вернулись в то положение, в котором находились перед началом внутреннего цикла.

6 нояб. 2012 г. 16:21:47
Комментарии

Я отредактировал свой первый пост, но не могу заставить это работать правильно. Хотя уверен, что делаю что-то не так.

andy andy
6 нояб. 2012 г. 17:50:28

Вы сохраняли резервную копию глобальных данных поста? Добавьте global $post;$backup=$post; перед внутренним циклом и $post=$backup; после внутреннего цикла.

Mridul Aggarwal Mridul Aggarwal
6 нояб. 2012 г. 18:41:15

Ах, это работает, когда я пишу вот так (см. правку в первом посте), но the_post_thumbnail больше не работает.

andy andy
6 нояб. 2012 г. 18:47:34

$post=$backup; должен идти после цикла while, то есть после endwhile;

Mridul Aggarwal Mridul Aggarwal
6 нояб. 2012 г. 18:52:31

А, точно, теперь работает. Не мог бы ты объяснить, что делает global $post;$backup=$post; в контексте цикла? Просто чтобы я понимал, что на самом деле делаю.

И спасибо за помощь, ценю это!

andy andy
6 нояб. 2012 г. 19:03:24

добавил объяснение

Mridul Aggarwal Mridul Aggarwal
6 нояб. 2012 г. 19:26:25

нужно ли использовать wp_reset_postdata() во внутреннем запросе?

chap chap
12 июн. 2015 г. 10:16:46

после внутреннего запроса нужно использовать wp_reset_query

Lane Lane
30 янв. 2016 г. 01:26:16
Показать остальные 3 комментариев
0
10

Вы также можете использовать WP_Query::reset_postdata() для этого.

$query = new WP_Query($args);

while ($query->have_posts()) :

    // инициализация для $inner_args и сохранение текущего глобального $post
    $inner_query = new WP_Query($inner_args);

    while ($inner_query->have_posts()) :
        // выполнение действий
    endwhile;

    // восстановление глобального $post из ранее сохраненной резервной копии
    $query->reset_postdata();

endwhile;
10 нояб. 2016 г. 18:28:16
1

Добавьте global $post;$backup=$post; перед внутренним циклом while и $post=$backup; после внутреннего цикла while.

(Почему Mridul Aggarwal не написал реальный код в своей части?)

3 апр. 2021 г. 14:28:28
Комментарии

Ваш ответ неплохо начинается. Пожалуйста, рассмотрите возможность объяснить, как и почему этот код решает проблему, чтобы другие могли научиться. Ознакомьтесь с руководством по ответам для получения дополнительных советов.

Matthew Brown aka Lord Matt Matthew Brown aka Lord Matt
3 апр. 2021 г. 22:54:44