Где следует сбросить postdata?


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

После циклического выполнения отдельного запроса эта функция восстанавливает $post global в текущую запись в основном запросе.

С фрагментом из:

<?php
// example args
$args = array( 'posts_per_page' => 3 );

// the query
$the_query = new WP_Query( $args );
?>

<?php if ( $the_query->have_posts() ) : ?>

    <!-- start of the secondary loop -->
    <?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
        <?php the_title(); ?>
        <?php the_excerpt(); ?>
    <?php endwhile; ?>
    <!-- end of the secondary loop -->

    <!-- put pagination functions here -->

    <!-- reset the main query loop -->
    <?php wp_reset_postdata(); ?>

<?php else:  ?>

    <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>

<?php endif; ?>

Но когда я ссылаюсь на другие способы, такие как " Как исправить разбивку на страницы для пользовательских циклов? "это после условного:

// Output custom query loop
if ( $custom_query->have_posts() ) :
    while ( $custom_query->have_posts() ) :
        $custom_query->the_post();
        // Loop output goes here
    endwhile;
endif;
// Reset postdata
wp_reset_postdata();

Не было бы уместно сделать это впоследствии, а не в рамках условия have_posts(), потому что, если вы используете оператор else, аргументы не сбрасываются, если у вас нет сообщений. Итак, мой вопрос в том, куда следует wp_reset_postdata() идти?

Author: DᴀʀᴛʜVᴀᴅᴇʀ, 2017-05-24

3 answers

Краткая версия:

Как сказал Том Дж. Ноуэлл,

Вы не должны убирать, если нечего убирать

Длинная версия:

Однако, если вы поместите wp_reset_postdata() после (или вне) цикла, он все равно будет работать отлично. Я использовал эту функцию в различных сценариях, включая что-то вроде этого:

dynamic_sidebar( 'main-sidebar' );
wp_reset_postdata();

Причина заключалась в том, что какой-то виджет запрашивал сообщения, не убирая за собой.

Просто имейте в виду, какой запрос вы хотите сбросить. В примере Тома, независимо от того, находится ли wp_reset_postdata в операторе if или нет, как только он будет вызван, у вас возникнут проблемы, потому что он напрямую вернется к основному сообщению вместо родительского пользовательского цикла.

Что делает функция, так это указывает объекту WP_Query восстановить текущую запись в глобальную область. Поскольку это функция, а не метод, то есть единственный объект, с которым она работает - глобальный $wp_query экземпляр WP_Query объект.

Если у вас есть пользовательские циклы, в которых вы используете недавно сгенерированный WP_Query, вам следует использовать метод reset_postdata этого запроса:

$pages = new WP_Query( 'post_type=page' );
while( $pages->have_posts() ) {
    $pages->the_post();

    // Page title
    echo '<h1>'; the_title();  echo '</h1>';

    $books = new WP_Query( 'post_type=book&...' );
    if( $books->have_posts() ) {
        while( $books->have_posts() ) {
            $books->the_post();

            // Book title
            echo '<li>'; the_title(); echo '</li>';
        }

        // Don't go back to the global post, go back to the "page"
        // wp_reset_postdata();
        $pages->reset_postdata();
    }

    // Page content
    the_content();
}

// Finally, reset the main query
wp_reset_postdata();

Надеюсь, это подводит итог:)

 3
Author: Radoslav Georgiev, 2017-05-24 16:32:30

Вы сделали это правильно! Это неправильный пример. К сожалению, почти все примеры запросов имеют эту проблему

Обычно размещение его после условного не имеет вредных последствий, но при вложении циклов это может вызвать проблемы в крайних случаях. Для 99,9 % случаев использования это не проблема.

Поместив его в условное условие, вы обеспечили сброс данных postdata только в том случае, если они были изменены.

Рассмотрим этот крайний случай:

while( have_posts() ) {
    the_post();
    ... stuff...
    $q = new WP_Query( $args );
    if ( $q->have_posts() ) {
        while( $q->have_posts() ) {
            $q->the_post();
            the_title();
            $related_posts = new WP_Query( $args2 );
            if ( $related_posts->have_posts() ) {
                while( $related_posts->have_posts() ) {
                    $related_posts->the_post();
                    //
                }
            }
            wp_reset_postdata();

            the_content();
        }
    }
    wp_reset_postdata();
}

Здесь мы делаем вложенный цикл для извлечения связанных записей, но обратите внимание, что произойдет, если связанные записи не будут найдены и $related_posts->have_posts() вернет false, данные post будут сброшены обратно в основной цикл, и вы получите содержимое публикации основных запросов, а не запрос $q

 4
Author: Tom J Nowell, 2017-05-24 14:57:36

Обычно я использую его вне оператора if($query->have_posts()). Таким образом, вы можете быть уверены, что даже если сообщения не будет, он сбросит запрос. У меня нет никаких проблем с размещением его после (и снаружи) оператора if($query->have_posts()).

 0
Author: Hossein, 2017-05-24 14:04:25