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ループの基本 では新着情報でよく見る、下記をつくってみましょう。 […]