query_posts、have_posts でハマったこと

WordPress

query_posts で $posts は上書きされない

$posts にはそのページで表示する投稿情報の一覧が格納される。query_posts を発行することで取得する投稿を変更することができるが、このとき $posts は変更されないようだ。

ただ、表示される情報は確かに変更されるので、どこの情報が変更されるのか調べたところ、$wp_query->posts の情報が変更されるようだ。

// index.php
var_dump( count( $posts ) ); // = 10
var_dump( count( $wp_query->posts ) ); // = 10
query_posts( array( 'posts_per_page' => 5 ) );
var_dump( count( $posts ) );  // = 10
var_dump( count( $wp_query->posts ) ); // = 5

WordPressループ内で have_posts を使うと無限ループになる。

ページに表示される投稿の一覧を取得してゴニョゴニョするショートコードを作成した。その際、WordPressループを使用して投稿の一覧を取得・処理をするコードを書いた。そのショートコードを記事内に記述しページを表示したところ、無限ループが発生し、投稿内容が無限に繰り返し表示するようになってしまった。

調べてみると、英語版のCodexに次のような記述が。

Calling this function within the loop will cause an infinite loop. (訳:ループ内で、この関数を呼び出すと、無限ループが発生します。)

解決策

WordPressループは使用せず、$wp_query->posts を foreach で回すようにコードを変更することで解決できた。

add_shortcode( 'hogeshortcode', 'hogeshortcode' );
function hogeshortcode( $atts ) {
    /* このコードは無限ループ!
    if ( have_posts() ) {
        while ( have_posts() ) {
            the_post();
            〜処理〜
        }
    }
    */

    // 下記のように変更すればOK
    global $wp_query, $post;
    foreach ( $wp_query->posts as $post ) {
        setup_postdata( $post );
        〜処理〜
    }
    wp_reset_postdata( $post );
}

query_postsで条件変更しても「MW Google Maps」に表示されるピンが変更されないので調べてみた。旧バージョンをお使いの方はバージョンアップしてください。

  • ブックマーク
  • Feedly

この記事を書いた人

キタジマタカシ

長崎在住、フリーランスのWordPress テーマ / プラグインデベロッパー。 多数のプロダクトをオープンソースで開発・公開しています。現在は WordPress 有料テーマ Snow Monkey を開発・販売しています。