web-dev-qa-db-ja.com

Postdataをどこでリセットしますか?

Q&Aでこれを検索しましたが、見つかりませんでした。サイト全体で答えを読むと、wp_reset_postdata()は条件付きでhave_posts()は条件付きで、複数の領域にはめ込まれています。 wp_reset_postdata() のドキュメントを読むと、以下のように書かれています。

別のクエリをループした後、この関数はメインクエリの現在の投稿にグローバル$ postグローバルを復元します。

スニペットを使って:

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

もしあなたがelse文を使っていても投稿がなければ引数はリセットされないので、後でそれを持ってhave_posts()条件の中に入れないことは適切ではないでしょうか。それで私の質問はwp_reset_postdata()はどこへ行くべきか?

短縮版:

トムJノウェルが言ったように、

掃除するものが何もなければ、掃除をしてはいけません

ロングバージョン:

しかし、wp_reset_postdata()をループの後(またはループの外側)に入れても、それでも完全にうまくいきます。私はこのようなものを含むさまざまなシナリオで関数を使用しました:

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

その理由は、いくつかのウィジェットがそれ自身の後にクリーニングすることなく投稿を問い合わせていたことです。

どのクエリをリセットしたいのかを覚えておいてください。 Tomの例では、wp_reset_postdataifステートメント内にあるかどうかにかかわらず、一度呼び出されると、親カスタムループではなくメインの投稿に直接戻るため、問題が発生します。

この関数が行うことは、現在の投稿をグローバルスコープに復元するように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

あなたはそれを正しくしました! それは間違っている例です 。残念ながら、ほとんどすべてのクエリ例でこの問題が発生しています

通常、条件式の後に置いても悪影響はありませんが、ループを入れ子にすると、Edgeのケースで問題が発生する可能性があります。 99.9%のユースケースでは、これは問題になりません。

それを条件付きの中に置くことによって、ポストデータが変更された場合にのみリセットされることを確実にしました。

このEdgeのケースを考えてください。

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を返すとpostdataがメインループのものにリセットされ、メインクエリの投稿内容は得られません$qクエリのそれ

4
Tom J Nowell

通常私はif($query->have_posts())文の外側でそれを使います。これにより、投稿がなくてもクエリがリセットされることを確認できます。 if($query->have_posts())ステートメントの後(そして外側)に置いても問題ありません。

0
Hossein