WordPressループの基本
<?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <!-- 表示内容を記述 --> <h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2> <div <?php post_class(); ?> id="post-<?php the_ID(); ?>"> <?php the_content(); ?> </div> <?php endwhile; ?> <?php endif; ?>
これは WordPressループの基本構文ですね。
このループ構文を記述すれば、投稿記事一覧、個別記事、固定ページ、カテゴリーアーカイブ、年月別アーカイブ、フィード、検索、などなど、それぞれのページに必要なデータが表示されます。
これって不思議だと思いませんか?
「○○のデータを取得する」とかいう条件がどこにもありません。
これを紐解いていくと WordPress のループの仕組みを深く理解することができるようになります。
WP Query オブジェクト
WP_Query
WP_Query は wp-includes/query.php に定義されているクラスで、WordPress への複雑なリクエストを取り扱います。
グローバル変数 $wp_query に、現在のリクエストを定義する情報を与えることで、どのタイプのクエリを扱っているのかを確定し、要求されたデータを取り出します。
つまり、特定のURLにアクセスするだけで、そのページに必要なデータを自動的に取得して、グローバル変数 $wp_query に格納してくれる のです。
では、グローバル変数 $wp_query とはどのようなものでしょうか?
投稿記事一覧ページのテンプレートの一番はじめに以下のコードを記述して、$wp_query を表示させてみましょう。
<?php print_r($wp_query); ?>
じゃんッ!↓
WP_Query Object ( [query_vars] => Array ( [error] => [m] => 0 [p] => 0 [post_parent] => [subpost] => [subpost_id] => [attachment] => [attachment_id] => 0 [name] => [static] => [pagename] => [page_id] => 0 [second] => [minute] => [hour] => [day] => 0 [monthnum] => 0 [year] => 0 [w] => 0 [category_name] => [tag] => [cat] => [tag_id] => [author_name] => [feed] => [tb] => [paged] => 0 [comments_popup] => [meta_key] => [meta_value] => [preview] => [s] => [sentence] => [fields] => // 省略 ) )
たくさん出てきましたね〜。
最初の方には関連するグローバル変数がずらっと並びます。
注目すべきは、このずーっと下の方にある、[request] と [posts] です。
[request] => SELECT SQL_CALC_FOUND_ROWS wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10 [posts] => Array ( [0] => stdClass Object ( [ID] => 187 [post_author] => 1 [post_date] => 2012-02-13 15:22:35 [post_date_gmt] => 2012-02-13 06:22:35 [post_content] => 投稿3の内容 [post_title] => 投稿3 [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => open [post_password] => [post_name] => %e6%8a%95%e7%a8%bf3 [to_ping] => [pinged] => [post_modified] => 2012-02-13 15:22:35 [post_modified_gmt] => 2012-02-13 06:22:35 [post_content_filtered] => [post_parent] => 0 [guid] => http://localhost/wordpress/dev/?p=187 [menu_order] => 0 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) [1] => stdClass Object ( [ID] => 185 [post_author] => 1 [post_date] => 2012-02-13 15:22:03 [post_date_gmt] => 2012-02-13 06:22:03 [post_content] => 投稿2の内容 [post_title] => 投稿2 [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => open [post_password] => [post_name] => %e6%8a%95%e7%a8%bf2 [to_ping] => [pinged] => [post_modified] => 2012-02-13 15:22:03 [post_modified_gmt] => 2012-02-13 06:22:03 [post_content_filtered] => [post_parent] => 0 [guid] => http://localhost/wordpress/dev/?p=185 [menu_order] => 0 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) // 省略 ) [post] => stdClass Object ( [ID] => 187 [post_author] => 1 [post_date] => 2012-02-13 15:22:35 [post_date_gmt] => 2012-02-13 06:22:35 [post_content] => 投稿3の内容 [post_title] => 投稿3 [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => open [post_password] => [post_name] => %e6%8a%95%e7%a8%bf3 [to_ping] => [pinged] => [post_modified] => 2012-02-13 15:22:35 [post_modified_gmt] => 2012-02-13 06:22:35 [post_content_filtered] => [post_parent] => 0 [guid] => http://localhost/wordpress/dev/?p=187 [menu_order] => 0 [post_type] => post [post_mime_type] => [comment_count] => 0 [filter] => raw ) )
必要なデータを取得するクエリが [request] で、取得されたデータが [posts] だということが分かるでしょう。
さらに、[post] には、[posts] のデータが順番にセットされていきます。
もう一度、WordPressループの基本構文を見てください。
<?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <!-- 表示内容を記述 --> <h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2> <div <?php post_class(); ?> id="post-<?php the_ID(); ?>"> <?php the_content(); ?> </div> <?php endwhile; ?> <?php endif; ?>
the_posts() 関数というのがあります。
この関数こそが、 取得したデータを順番にグローバル変数 $post に読み込んでいるのです。
もしこの関数を記述しなければ、 $post は永遠に最初のデータから動かないので、無限ループになります。
WordPressのテンプレートはクエリベースである
ここで重要なことが判明してきます。
最初に「特定のURLにアクセスするだけで、そのページに必要なデータを自動的に取得して、グローバル変数 $wp_query に格納してくれる」と書きましたが、正確には「URLから必要なデータのクエリを発行し、グローバル変数 $wp_query に格納した後、テンプレート階層に従ってデータを表示する。」となります。
この流れをよーく覚えておきましょう。
WordPressループを変更する query_posts()
WordPressループを変更するには、query_posts() を使います。
これは、取得するデータのクエリを動的に発行して $wp_query の値を変更することを意味します。
<?php query_posts(引数); ?> <?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <!-- 表示内容を記述 --> <?php endwhile; ?> <?php endif; ?> <?php wp_reset_query(); ?>
引数として条件を与えることで、データを取得するクエリを変更します。
条件の指定方法はこちら→ query_posts()
最後に wp_reset_query() で、動的に変更した $wp_query をリセットすることを忘れないでください。
マルチループを生成する get_posts
ループを生成する関数には、他に get_posts() があります。
get_posts() は、マルチループを生成するための関数です。
<?php $myposts = get_posts(引数); ?> <?php foreach($myposts as $post) : setup_postdata($post); ?> <!-- 表示内容を記述 --> <?php endforeach; ?>
query_posts() と同様に、引数で条件を指定することで、マルチループを生成することができます。
生成できるループは query_posts() とほぼ同じですが、両者には決定的な違いがあります。
query_posts と get_posts の違い
query_posts と get_posts の違い
get_posts() は、単にデータを取得するだけで、グローバル変数 $wp_query には影響を与えません。
query_posts() は、グローバル変数 $wp_query を変更します。
この違いは重要です。
個別記事ページ(シングルページ)を表示させてみましょう。
一番最初にグローバル変数 $wp_query の内容を表示させてみると、[is_single] => 1 となっており、シングルページのフラグが立っています。シングルページなのですから当然です。
ここで、個別記事ページの一部に、固定ページの一覧を表示させたいとします。
query_posts() でも get_posts() でも、どちらでも固定ページ一覧のループは生成可能です。
しかし、この時は、get_posts() を使うべきです。
query_posts() は使ってはいけません。
それはなぜか?
ループ内に is_single() という条件分岐タグを入れてみれば分かります。
get_posts() を使えば、グローバル変数 $wp_query には影響を与えませんので、is_single() は正常に動作します。
<?php $myposts = get_posts('post_type=page'); ?> <?php foreach($myposts as $post) : setup_postdata($post); ?> <?php if (is_single()) : ?> <?php the_title(); ?> <?php endif; ?> <?php endforeach; ?>
一方、query_posts() では、グローバル変数 $wp_query が上書きされる、つまり [is_single] => となり、is_single() ではシングルページと判定されません。
<?php query_posts('post_type=page'); ?> <?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <?php if (is_single()) : ?> <?php the_title(); ?> <?php endif; ?> <?php endwhile; ?> <?php endif; ?> <?php wp_reset_query(); ?>
“query_posts() は WordPressループ内で使うべき” と言われるのはこういうことです。
まとめ
・WordPress が自動的に取得したデータは、グローバル変数 $wp_query に格納される。
・WordPressループの表示条件を変更したい場合は query_posts() を使う。
・WordPressループとは別に、新しいマルチループを生成する場合は get_posts() を使う。
Comments
「manablog」さんの「『プラグインなし』で人気記事一覧を出力する方法」で分からなかったところがすっきりしました。ありがとうございました。
[…] http://hijiriworld.com/web/wordpress-loop/ […]
[…] WordPress ループの仕組み query_posts() と get_posts() の違い | hijiriworld Web […]
[…] WordPressのループの仕組みを深く知る query_posts() と get_posts() の違い http://hijiriworld.com/web/wordpress-loop/ […]
[…] WordPress ループの仕組み query_posts() と get_posts() の違い | hijiriworld Web http://hijiriworld.com/web/wordpress-loop/ posted at 19:37:44 […]
[…] !?なんでー!!ということで、またもググったところ、query_postsを変更してしまうと、条件分岐は使えないとのこと。 WordPress ループの仕組み query_posts() と get_posts() の違い | hijiriworld Web […]
勉強になります
参考にしていただけたようで良かったです^^
[…] 「Webデザインレシピ:WordPressでブログじゃないWebサイトを作るときのいろいろ(サンプル付き)」 […]
[…] WordPressループの基本 では新着情報でよく見る、下記をつくってみましょう。 […]