当サイト、Codex 日本語版は今後積極的な更新は行わない予定です。後継となる新ユーザーマニュアルは、https://ja.wordpress.org/support/ にあります。
万が一、当サイトで重大な問題を発見した際などは、フォーラムWordSlack #docs チャンネルでお知らせください。</p>

「ループ」の版間の差分

提供: WordPress Codex 日本語版
移動先: 案内検索
(The Loopから移設)
 
(重複している冒頭の注意文を削除。)
 
(3人の利用者による、間の14版が非表示)
1行目: 1行目:
{{NeedTrans}}
+
{{テーマ・テンプレートガイド}}
 
+
 
__TOC__
 
__TOC__
「'''ループ'''」は、WordPress の投稿を表示するために使います。このループを使えば、現在のページに表示される各投稿を処理したり、ループタグ内で指定された条件に沿って投稿の形式を整えたりできます。ループの開始部分と終了部分の間に書きこんだ [[用語集#HTML|HTML]] や [[用語集#PHP|PHP]] のコードは、各投稿の表示に使われます。
+
「'''ループ'''」は、WordPress の投稿を表示するために使われるPHPコードです。このループを使えば、現在のページに表示される各投稿を処理したり、ループタグ内で指定された条件に沿って投稿の形式を整えたりできます。ループの開始部分と終了部分の間に書きこんだ [[用語集#HTML|HTML]] や [[用語集#PHP|PHP]] のコードは、各投稿の表示に使われます。
  
[[テンプレートタグ]]やプラグインの説明内に「このタグ(プラグイン)はループ内で使います」とある場合、タグが各投稿で繰り返して表示されます。
+
[[テンプレートタグ]]や[[プラグイン]]の説明内に「このタグ(プラグイン)はループ内で使います」とある場合、タグが各投稿で繰り返して表示されます。例として、以下が各投稿にデフォルトでループ内に含まれます。
 
+
以下はループ内に含める投稿の情報例です。
+
  
 
* 投稿のタイトル - <tt>[[テンプレートタグ/the_title|the_title()]]</tt>
 
* 投稿のタイトル - <tt>[[テンプレートタグ/the_title|the_title()]]</tt>
 
* 投稿の公開日時 - <tt>[[テンプレートタグ/the_time|the_time()]]</tt>
 
* 投稿の公開日時 - <tt>[[テンプレートタグ/the_time|the_time()]]</tt>
 
* 属するカテゴリー - <tt>[[テンプレートタグ/the_category|the_category()]]</tt>
 
* 属するカテゴリー - <tt>[[テンプレートタグ/the_category|the_category()]]</tt>
* 投稿の本文 - <tt>[[テンプレートタグ/the_content|the_content()]]</tt>
+
<!--* 投稿の本文 - <tt>[[テンプレートタグ/the_content|the_content()]]</tt>-->
  
さらに他の[[テンプレートタグ]]を使ったり <tt>$post</tt> 変数にアクセスしたりして、投稿に関する様々な情報を表示することもできます。
+
さらに他の[[テンプレートタグ]]を使ったり、詳しい人ならば <tt>$post</tt> 変数にアクセスしたりして、投稿に関する様々な情報を表示することもできます。
  
 
ループに始めて触れる人は、[[The_Loop_in_Action|ループの使用例]]/[[:en:The_Loop_in_Action|en]] ページも参照してください。
 
ループに始めて触れる人は、[[The_Loop_in_Action|ループの使用例]]/[[:en:The_Loop_in_Action|en]] ページも参照してください。
  
 +
<div id="Using_The_Loop">
 
== ループの使い方 ==
 
== ループの使い方 ==
 
+
</div>
 
ループは <tt>index.php</tt> などのテンプレートファイルに含め、投稿の情報を表示するために使います。
 
ループは <tt>index.php</tt> などのテンプレートファイルに含め、投稿の情報を表示するために使います。
  
 
[[Theme Development|テーマ]]のテンプレートの最初で、ヘッダーテンプレートを必ず呼び出すようにしてください。もしループをテンプレート以外の自分のデザインで使っている場合、<tt>WP_USE_THEMES</tt> を <tt>false</tt> に設定します。
 
[[Theme Development|テーマ]]のテンプレートの最初で、ヘッダーテンプレートを必ず呼び出すようにしてください。もしループをテンプレート以外の自分のデザインで使っている場合、<tt>WP_USE_THEMES</tt> を <tt>false</tt> に設定します。
  
<pre><?php define('WP_USE_THEMES', false); get_header(); ?></pre>
+
<?php define( 'WP_USE_THEMES', false ); get_header(); ?>
  
== ループの例 ==
+
ループはここから始まり、
  
=== 特定のカテゴリにある投稿のスタイルを変更する ===
+
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
  
以下のコードは、 <tt>[[テンプレートタグ/in_category|in_category()]]</tt> [[テンプレートタグ]]を使ってカテゴリー番号が3の投稿に他とは別のCSSクラス名を割り当てる場合の例です。CSS(style.css)内でこのクラスの宣言を追加・編集することにより、カテゴリー3の投稿にのみ特別なスタイルを加えることができます。
+
ここで終わります。
 +
 
 +
<?php endwhile; else : ?>
 +
&lt;p&gt;<?php _e( 'Sorry, no posts matched your criteria.' ); ?>&lt;/p&gt;
 +
<?php endif; ?>
 +
 
 +
PHPの制御構造を用いることで、このような表現も可能です。
 +
 
 +
<?php
 +
if ( have_posts() ) {
 +
while ( have_posts() ) {
 +
the_post();
 +
//
 +
// 投稿がここに表示される
 +
//
 +
} // end while
 +
} // end if
 +
?>
 +
 
 +
<div id="Loop_Examples">
 +
== ループの例 ==
 +
</div>
 +
<div id="Style_Posts_From_Some_Category_Differently">
 +
=== 特定のカテゴリーにある投稿のスタイルを変更する ===
 +
</div>
 +
以下のコードは各投稿をのタイトル ([[パーマリンクの使い方|パーマリンク]]として用いられるもの)、カテゴリー、内容を表示するものです。これはまた、<tt>[[テンプレートタグ/in_category|in_category()]]</tt> [[テンプレートタグ]]を使ってカテゴリー番号が3の投稿に他とは別のCSSクラス名を割り当てています。CSS(style.css)内でこのクラスの宣言を追加・編集することにより、カテゴリー3の投稿にのみ特別なスタイルを加えることができます。
  
 
<tt><nowiki><!-- --></nowiki></tt> というHTMLコメントで囲まれた部分は、実際にブラウザでは表示されません。ここではコードを分かりやすくするためにHTMLコメントで囲んだ説明を挿入していますが、実際にはテンプレート内に書き込まなくてもかまいません。
 
<tt><nowiki><!-- --></nowiki></tt> というHTMLコメントで囲まれた部分は、実際にブラウザでは表示されません。ここではコードを分かりやすくするためにHTMLコメントで囲んだ説明を挿入していますが、実際にはテンプレート内に書き込まなくてもかまいません。
40行目: 63行目:
 
  <!-- もし属している場合、"post-cat-three"というCSSクラスのdivボックスを表示 -->
 
  <!-- もし属している場合、"post-cat-three"というCSSクラスのdivボックスを表示 -->
 
  <!-- それ以外の場合、"post"というCSSクラスのdivボックスを表示 -->
 
  <!-- それ以外の場合、"post"というCSSクラスのdivボックスを表示 -->
  <?php if ( in_category('3') ) { ?>
+
  <?php if ( in_category( '3' ) ) : ?>
          <div class="post-cat-three">
+
<div class="post-cat-three">
  <?php } else { ?>
+
  <?php else : ?>
          <div class="post">
+
<div class="post">
  <?php } ?>
+
  <?php endif; ?>
  
 
  <!-- 投稿のタイトルとパーマリンクを表示 -->
 
  <!-- 投稿のタイトルとパーマリンクを表示 -->
73行目: 96行目:
 
'''注:''' [[用語集#HTML|HTML]]コードをテンプレート内に書く場合は、'''必ず''' <tt><?php &nbsp;?></tt> というPHP開始・終了タグの外側に書かなければなりません。逆に、[[用語集#PHP|PHP]]コードは、必ず <tt><?php &nbsp;?></tt> タグの内側に書きます。上記のように、<tt>if</tt> や <tt>else</tt> ステートメント内でもPHPコードを一時的に閉じ、HTMLコードを書くことができます。
 
'''注:''' [[用語集#HTML|HTML]]コードをテンプレート内に書く場合は、'''必ず''' <tt><?php &nbsp;?></tt> というPHP開始・終了タグの外側に書かなければなりません。逆に、[[用語集#PHP|PHP]]コードは、必ず <tt><?php &nbsp;?></tt> タグの内側に書きます。上記のように、<tt>if</tt> や <tt>else</tt> ステートメント内でもPHPコードを一時的に閉じ、HTMLコードを書くことができます。
  
=== Exclude Posts From Some Category ===
+
<div id="Exclude_Posts_From_Some_Category">
 
+
=== 特定カテゴリーの投稿を除外する ===
This example can be used to exclude a certain Category or Categories from being displayed.  In this case, posts from Categories 3 and 8 are excluded.  The example is different than the [[#Style Posts From Some Category Differently|example above]] in that it makes a change to the [[テンプレートタグ/query_posts|query]] itself.
+
</div>
 +
この例は特定のカテゴリーを表示させない場合を示します。この場合、カテゴリー3と8の投稿を除外します。この例は[[#Style Posts From Some Category Differently|上記の例]]とは異なり、[[テンプレートタグ/query_posts|クエリー]]自身を変更しています。
  
 
  <nowiki>
 
  <nowiki>
  <?php query_posts($query_string . '&cat=-3,-8'); ?>
+
  <?php $query = new WP_Query( 'cat=-3,-8' ); ?>
  <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
+
  <?php if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); ?>
  
 
  <div class="post">
 
  <div class="post">
87行目: 111行目:
  
 
  <!-- Display the date (November 16th, 2009 format) and a link to other posts by this posts author. -->
 
  <!-- Display the date (November 16th, 2009 format) and a link to other posts by this posts author. -->
  <small><?php the_time('F jS, Y') ?> by <?php the_author_posts_link() ?></small>
+
  <small><?php the_time( 'F jS, Y' ); ?> by <?php the_author_posts_link(); ?></small>
 
   
 
   
 
   <div class="entry">
 
   <div class="entry">
    <?php the_content(); ?>
+
  <?php the_content(); ?>
 
   </div>
 
   </div>
  
   <p class="postmetadata">Posted in <?php the_category(', '); ?></p>
+
   <p class="postmetadata"><?php _e( 'Posted in' ); ?> <?php the_category( ', ' ); ?></p>
 
  </div> <!-- closes the first div box -->
 
  </div> <!-- closes the first div box -->
  
  <?php endwhile; else: ?>
+
  <?php endwhile;  
  <p>Sorry, no posts matched your criteria.</p>
+
wp_reset_postdata();
 +
else : ?>
 +
  <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
 
  <?php endif; ?></nowiki>
 
  <?php endif; ?></nowiki>
  
'''Note''': If you use this example for your main page, you should use a different [[テンプレート|Template]] for your [[Category Templates|Category archives]], otherwise, WordPress will exclude all posts in Category 3, even when viewing that Category Archive!  However, if you want to use the same template file, you can avoid this by using the <tt>[[関数リファレンス/is_home|is_home()]]</tt> tag to ensure posts from Category 3 will only be excluded from the main page: 
+
 
 +
'''''': この例をメインページに用いる場合、違う[[テンプレート]][[Category Templates|カテゴリーページ]]に適用させる必要があります。さもなくば、WordPressは、カテゴリーアーカイブを含めた全てのページから、カテゴリー3と8の投稿を除外してしまいます。しかし、同じテンプレートファイルを使いたい場合、<tt>[[関数リファレンス/is_home|is_home()]] </tt>タグを用いることで、カテゴリー3と8の投稿がメインページからのみ除外されるようにすることができます。
 +
 
 
  ...
 
  ...
 
  <?php if ( is_home() ) {
 
  <?php if ( is_home() ) {
  query_posts($query_string . '&cat=-3');
+
  $query = new WP_Query( 'cat=-3,-8' );
  }
+
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post();  
 +
  } else {
 +
...
 
  ?>
 
  ?>
 
  ...
 
  ...
There are other [[Conditional Tags]] that can be used to control the output depending on whether or not a particular condition is true with respect to the requested page.
+
他にも[[Conditional Tags|条件分岐タグ]]を用いることで、ページに対する特定の条件が''true''であるか否かで出力をコントロールすることができます。
  
==複数のループ==
+
<div id="Multiple_Loops">
  
 +
==複数のループ==
 +
</div>
 
この章ではループの発展的用途について解説します。少々技術的な内容ですが、怖がらずに読んでください。簡単なところから徐々に発展した内容に入っていきます。ほんの少しの常識や我慢、そして熱意があれば、あなたも複数のループを使うことが出来るでしょう。
 
この章ではループの発展的用途について解説します。少々技術的な内容ですが、怖がらずに読んでください。簡単なところから徐々に発展した内容に入っていきます。ほんの少しの常識や我慢、そして熱意があれば、あなたも複数のループを使うことが出来るでしょう。
  
はじめに、<b>「なぜ複数のループが必要なのか?」</b>という点について考えてみましょう。おそらくあなたは<b>何か</b>をある投稿のグループに対して行い、<b>別の何か</b>を他の投稿のグループ対して行ったけれど、<u>同じページが両方のグループに表示されてしまった</u>のでしょう。Something could mean almost anything; you are only limited by your PHP skill and your imagination.
+
はじめに、<b>「なぜ複数のループが必要なのか?」</b>という点について考えてみましょう。おそらくあなたは<b>何か</b>をある投稿のグループに対して行い、<b>別の何か</b>を他の投稿のグループに対して行ったものの、<u>同じページが両方のグループに表示されてしまった</u>のでしょう。「何か」というのは「何にでも」という事になり得ます。あなたは今、PHPのスキルと想像に縛られています。
  
 
では、例に入りましょう。まずは普通のループから。
 
では、例に入りましょう。まずは普通のループから。
  
      <?php if (have_posts()) : ?>
+
<?php if ( have_posts() ) : ?>
                <?php while (have_posts()) : the_post(); ?>     
+
<?php while ( have_posts() ) : the_post(); ?>     
      &lt;!-- 何かの処理 ... --&gt;
+
&lt;!-- なにかの処理 ... --&gt;
      <?php endwhile; ?>
+
<?php endwhile; ?>
 +
<?php endif; ?>
 +
 
  
 
(ソースコードを読むのに慣れている人は飛ばして下さい)。
 
(ソースコードを読むのに慣れている人は飛ばして下さい)。
 
これを日本語で言えば、以下の様になります。
 
これを日本語で言えば、以下の様になります。
もし投稿を表示できれば、次へと進む。
+
* もし投稿を表示できれば、次へと進む。
そして一覧に存在している投稿ごそれぞれに<tt>&lt;!-- 何かの処理 ... --&gt;</tt>を行う。
+
*          そして一覧に存在している投稿ごとそれぞれに、
最後の投稿にたどり着いたら、終了する。
+
*          <tt>&lt;!-- なにかの処理 ... --&gt;</tt>を行う。
ここでの<tt>&lt;!-- 何かの処理 ... --&gt;</tt>はテンプレートに依ります。
+
* 最後の投稿にたどり着いたら、終了する。
 +
ここでの <tt>&lt;!-- なにかの処理 ... --&gt;</tt> はテンプレートに依存します。
 +
 
 +
<tt>なにかの処理</tt>について: この例ではページの各投稿をどうフォーマットし、どう表示させるかというコード一式を表しています。ここに入るコードはWordPressでどう表現したいかに依って異なります。例えば、Kubrickのテーマの <tt>index.php</tt> を見た場合、
  
Aside on <tt>Do stuff</tt>: in this example it is simply a placeholder for a bunch of code that determines how to format and display each post on a page.  This code can change depending on how you want your WordPress to look.  If you look at the Kubrick theme’s index.php the <tt>do stuff</tt> section would be everything below:
+
<?php while ( have_posts() ) : the_post(); ?>
  
      <?php while (have_posts()) : the_post(); ?>
+
に続いて、この行が入ります。
To above:
+
  
      <?php comments_popup_link('No Comments &#187;', '1 Comment &#187;', '% Comments &#187;'); ?>
+
<?php comments_popup_link( 'No Comments &#187;', '1 Comment &#187;', '% Comments &#187;' ); ?>
  
An explanation for the coders out there:
+
コーダー向けの説明:
The <tt>have_posts()</tt> and <tt>the_post()</tt> are convenience wrappers around the global <tt>$wp_query</tt> object, which is where all of the action is.  The <tt>$wp_query</tt> is called in the blog header and fed query arguments coming in through <tt>GET</tt> and <tt>PATH_INFO</tt>.  The <tt>$wp_query</tt> takes the arguments and builds and executes a DB query that results in an array of posts.  This array is stored in the object and also returned back to the blog header where it is stuffed into the global <tt>$posts</tt> array (for backward compatibility with old post loops).
+
<tt>have_posts()</tt> <tt>the_post()</tt> は、全てのアクションであるグローバルな <tt>$wp_query</tt> オブジェクトを用いるのに便利なラッパーです。<tt>$wp_query</tt> はブログのヘッダーで呼び出され、<tt>GET</tt> <tt>PATH_INFO</tt> を通して来たクエリー引数が入力されます。<tt>$wp_query</tt> は引数を受け、ビルドし、データベースクエリーを実行し、投稿の配列を作成します。この配列はオブジェクト内に格納され、またグローバルの<tt>$posts</tt> 配列の中に (古い投稿ループとの後方互換性のために) 入っているブログのヘッダーに返されます。
  
Once WordPress has finished loading the blog header and is descending into the template, we arrive at our post Loop.  The <tt>have_posts()</tt> simply calls into <tt>$wp_query->have_posts()</tt> which checks a loop counter to see if there are any posts left in the post array.  And <tt>the_post()</tt> calls <tt>$wp_query->the_post()</tt> which advances the loop counter and sets up the global <tt>$post</tt> variable as well as all of the global post data.  Once we have exhausted the loop, <tt>have_posts()</tt> will return false and we are done.
+
WordPressがブログのヘッダーを読み込み終わり、テンプレートまでたどり着くと、投稿のループに到達します。ここで <tt>have_posts()</tt> <tt>$wp_query-&gt;have_posts()</tt>を呼び出し、ループカウンターと投稿配列に残った投稿の有無をチェックします。そして<tt>the_post()</tt> <tt>$wp_query-&gt;the_post()</tt> を呼びだし、ループカウンターを進め、グローバルの <tt>$post</tt> 変数と、全てのグローバル投稿データをセットアップします。ループが完了したら、<tt>have_posts()</tt> がfalseを返し、終了します。
  
 
<div id="Loop_Examples">
 
<div id="Loop_Examples">
145行目: 181行目:
 
</div>
 
</div>
  
Below are two example of using multiple loops.  The key to using multiple loops is that <tt>$wp_query</tt> can only be called once.  In order to get around this it is possible to re-use the query by calling <tt>rewind_posts()</tt> or by creating a new query object.  This is covered in example 1.  In example 2, using a variable to store the results of a query is covered.  Example 3 documents the use of <tt>update_post_caches();</tt> function to avoid common plugin problems.  Finally, ‘multiple loops in action’ brings a bunch of ideas together to document one way of using multiple loops to promote posts of a certain category on your blog’s homepage.
+
以下に複数ループの使用例を2つ示します。複数ループを使うための鍵は <tt>$wp_query</tt> が一度しか呼び出されないところにあります。これを回避するために、 <tt>rewind_posts()</tt> を呼び出してクエリーを再利用するか、新しいクエリーオブジェクトを生成します。これは[[#Multiple Loops Example 1|複数ループの例 1]]の内容です。[[#Multiple Loops Example 2|複数ループの例 2]]ではクエリーの結果を格納する変数を使うケースがを挙げています。最後に[[#Multiple Loops in Action|複数ループの使い方]]では、ブログのホームページに特定のカテゴリーの投稿を優先的に載せるために様々なアイディアを駆使した複数ループの使用方法の1つを記載しています。
  
 +
<div id="Multiple Loops Example 1">
 
=====複数ループの例 1=====
 
=====複数ループの例 1=====
 
+
</div>
 
二度目のループでも同じ様に処理を行うには<tt>rewind_posts()</tt>を呼び出して下さい。
 
二度目のループでも同じ様に処理を行うには<tt>rewind_posts()</tt>を呼び出して下さい。
 
この関数はループのカウンタをリセットし、別のループを実行出来るようにします。
 
この関数はループのカウンタをリセットし、別のループを実行出来るようにします。
  
  <?php rewind_posts(); ?>
+
<?php rewind_posts(); ?>
 
    
 
    
  <?php while (have_posts()) : the_post(); ?>
+
<?php while ( have_posts() ) : the_post(); ?>
    &lt;!-- Do stuff... --&gt;
+
&lt;!-- なにかの処理... --&gt;
  <?php endwhile; ?>
+
<?php endwhile; ?>
  
 
もし既に標準のクエリに関するループを終了したあと、別のクエリを使いたくなったら、<tt>$wp_query</tt>オブジェクトを<tt>query_posts()</tt>から呼び出すことが可能です。<tt>query_posts()</tt>は新しいクエリ、投稿リストを作り、ループをリセットします。
 
もし既に標準のクエリに関するループを終了したあと、別のクエリを使いたくなったら、<tt>$wp_query</tt>オブジェクトを<tt>query_posts()</tt>から呼び出すことが可能です。<tt>query_posts()</tt>は新しいクエリ、投稿リストを作り、ループをリセットします。
  
  // special_catカテゴリから10件の投稿を取り出します。
+
// special_cat カテゴリーから10件の投稿を取り出します。
  <?php query_posts('category_name=special_cat&showposts=10'); ?>
+
<?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>
 
   
 
   
  <?php while (have_posts()) : the_post(); ?>
+
<?php while ( have_posts() ) : the_post(); ?>
    &lt;!-- special_cat についての処理... --&gt;
+
&lt;!-- special_cat についての処理... --&gt;
  <?php endwhile;?>
+
<?php endwhile; ?>
  
 
もし標準のクエリを保持しておきたければ、新しいクエリオブジェクトを生成するという方法があります。
 
もし標準のクエリを保持しておきたければ、新しいクエリオブジェクトを生成するという方法があります。
  
  <?php $my_query = new WP_Query('category_name=special_cat&showposts=10'); ?>
+
  <?php $my_query = new WP_Query( 'category_name=special_cat&posts_per_page=10' ); ?>
 
   
 
   
  <?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
+
  <?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
  &lt;!-- Do special_cat stuff... --&gt;
+
&lt;!-- special_cat についての処理.... --&gt;
 
  <?php endwhile; ?>
 
  <?php endwhile; ?>
  
<tt>$wp_query</tt>用の<tt>have_posts()</tt> と <tt>the_post()</tt> が使えないので、新たなオブジェクト<tt>my_query</tt>を生成します。
 
(訳注: ただのhave_posts()やthe_posts()ではなく、事前に生成した$my_queryのメソッドであることに注意して下さい。)
 
  
=====複数ループの例 2=====
+
<tt>$wp_query</tt>用の<tt>have_posts()</tt> と <tt>the_post()</tt> が使えないので、新たなオブジェクト <tt>my_query</tt> を生成します。
 +
(訳注: ただの <tt>have_posts()</tt> や <tt>the_posts()</tt> ではなく、事前に生成した <tt>$my_query</tt> のメソッドであることに注意して下さい。)
  
Another version of using multiple Loops takes another tack for getting around the inability to use <tt>have_posts()</tt> and <tt>the_post()</tt>.  To solve this, you need to store the original query in a variable, then re-assign it with the other Loop. This way, you can use all the standard functions that rely on all the globals.
+
<div id="Multiple Loops Example 2">
 
+
=====複数ループの例 2=====
For example:
+
</div>
 +
複数ループを使うもう一つの方法は、<tt>have_posts()</tt> <tt>the_post()</tt> が使えないことに対する別の回避策を必要とします。これを解決するために、オリジナルのクエリー結果を変数に格納し、もう一方のループで再度割り当てる必要があります。これにより、全てのグローバルに依存する全ての標準機能を使うことができます。
  
  // going off on my own here
+
例:
 +
  // ここで脇にそれる
 
  <?php $temp_query = $wp_query; ?>
 
  <?php $temp_query = $wp_query; ?>
  &lt;!-- Do stuff... --&gt;
+
  &lt;!-- なにかの処理... --&gt;
 
   
 
   
  <?php query_posts('category_name=special_cat&posts_per_page=10'); ?>
+
  <?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>
 
   
 
   
  <?php while (have_posts()) : the_post(); ?>
+
  <?php while ( have_posts() ) : the_post(); ?>
  &lt;!-- Do special_cat stuff... --&gt;
+
&lt;!-- special_cat についての処理... --&gt;
 
  <?php endwhile; ?>
 
  <?php endwhile; ?>
+
 
  // now back to our regularly scheduled programming
+
  // ここで通常のプログラミングに戻る
 
  <?php $wp_query = $temp_query; ?>
 
  <?php $wp_query = $temp_query; ?>
  
'''Note:''' In PHP 5, objects are referenced with the "="-operator instead of copied like in PHP 4. To make Example 2 work in PHP 5 you need to use the following code:
+
''':''' PHP 4では<tt> "=" </tt>オペレーターでオブジェクトが参照されていましたが、PHP 5では<tt> "= clone" </tt>オペレーターで参照されます。例 2をPHP 5で動くようにするためには、以下のコードを用いる必要があります。
  
 
<pre>
 
<pre>
  // going off on my own here
+
  // ここで脇にそれる
 
  <?php $temp_query = clone $wp_query; ?>
 
  <?php $temp_query = clone $wp_query; ?>
 
  &lt;!-- Do stuff... --&gt;
 
  &lt;!-- Do stuff... --&gt;
 
   
 
   
  <?php query_posts('category_name=special_cat&posts_per_page=10'); ?>
+
  <?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>
 
   
 
   
  <?php while (have_posts()) : the_post(); ?>
+
  <?php while ( have_posts() ) : the_post(); ?>
  &lt;!-- Do special_cat stuff... --&gt;
+
&lt;!-- special_cat についての処理... --&gt;
 
  <?php endwhile; ?>
 
  <?php endwhile; ?>
 
  <?php endif; ?>
 
  <?php endif; ?>
 
   
 
   
  // now back to our regularly scheduled programming
+
  // ここで通常のプログラミングに戻る
 
  <?php $wp_query = clone $temp_query; ?>
 
  <?php $wp_query = clone $temp_query; ?>
 
</pre>
 
</pre>
  
However, this second example does not work in WordPress 2.1.
+
しかし、2つ目の例はWordPress 2.1では使うことはできません。
  
=====複数ループの例 3 - プラグイン=====
+
<div id="Multiple Loops in Action">
 +
====複数ループの使い方====
 +
</div>
 +
複数ループをどのように使うかを理解するための最適な方法は、その使用例を見せることです。最も一般的な複数ループの使い方は、2つ以上の投稿リストを1つのページに表示させることです。最新の投稿だけでなく、特定のカテゴリーからの投稿も注目させたい時にしばしば使われ方法です。
  
It has been found that some plugins don’t play nice with multiple loops.  In these cases it was discovered that some plugins which deal with the keyword(s) and tagging of posts, only work for the first instance of a loop in a page where that loop consists of a subset of total posts.  If you find that this is the case, you might want to try the following implementation of the basic loop which adds the <tt>update_post_caches($posts)</tt> function.  This function resets the post cache and is as yet undocumented.  This implementation would be used on the second loop in a page only if the first loop retrieves a subset of posts.
+
フォーマットとCSSに関する全ての問題は一旦脇において、2つの投稿リストを表示させたい場合を考えましょう。1つは最新の投稿 (標準的な最新10件の投稿)、もう1つは 'featured' カテゴリーからの最新投稿を1件だけを表示させるとします。'featured' カテゴリーからの投稿を一番最初に表示し、次に投稿のリスト (標準のもの) という順番で考えます。<b>重要なのは、両方のカテゴリーに表示させる投稿はあってはならないというところです。</b>
  
Simply amend:
+
<b>ステップ 1.</b> ‘featured’ カテゴリーから1つの投稿だけを取得する。
  
    <?php if (have_posts()) : ?>
+
<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
                <?php while (have_posts()) : the_post(); ?>  
+
while ( $my_query->have_posts() ) : $my_query->the_post();
      &lt;!-- Do stuff... --&gt;
+
$do_not_duplicate = $post->ID; ?>
    <?php endwhile; ?>
+
&lt;!-- なにかの処理... --&gt;
 +
<?php endwhile; ?>
  
to become:
 
  
    <?php if (have_posts()) : ?>
+
日本語ではこのコードはこのように読めます。
                <?php while (have_posts()) : the_post(); update_post_caches($posts); ?>
+
      &lt;!-- Do stuff... --&gt;
+
    <?php endwhile; ?>
+
  
====複数ループの使い方====
+
* <tt>$my_query</tt> は 'featured' と名付けられたカテゴリーからの全ての投稿を検索します。ただし、最新の投稿1件分だけ貰います。
 +
* そして一覧に存在している投稿ごとそれぞれに (この場合は1件ですが)
 +
* <tt>$do_not_duplicate</tt> という変数を、1行目で返された投稿のIDで設定します。
 +
* <tt>なにかの処理</tt>というのは、表示される投稿に関する全てのフォーマットオプションの処理です。
 +
* ループを終了します (この場合は1件ですが)
  
The best way to understand how to use multiple loops is to actually show an example of its use.  Perhaps the most common use of multiple loops is to show two (or more) lists of posts on one page.  This is often done when a webmaster wants to feature not only the very latest post written, but also posts from a certain category.
+
この時大事なのは、同じ投稿が2つのリストに出ないようにするために、 <tt>$do_not_duplicate</tt> の値が次のステップで必要とされることです。
  
Leaving all formatting and CSS issues aside, let us assume we want to have two lists of posts.  One which would list the most recent posts (the standard 10 posts most recently added), and another which would contain only one post from the category ‘featured’.  Posts in the ‘featured’ category should be shown first, followed by the second listing of posts (the standard).  <b>The catch is that no post should appear in both categories.</b>
+
<b>ステップ 2.</b> 2つ目のループで、X個の最新投稿を取得する (但し、1つを除く)
  
<b>Step 1.</b> Get only one post from the ‘featured’ category.
+
以下のコードでは、WordPress初期設定で定義されたX個の最新投稿を取得し、最初のループで保存された表示済みの投稿をセーブし、<tt>なにかの処理</tt>に従って表示させます。
  
  <?php $my_query = new WP_Query('category_name=featured&posts_per_page=1');
+
<?php if ( have_posts() ) : while ( have_posts() ) : the_post();  
  while ($my_query->have_posts()) : $my_query->the_post();
+
if ( $post->ID == $do_not_duplicate ) continue;?>
  $do_not_duplicate = $post->ID; ?>
+
&lt;!-- なにかの処理... --&gt;
    &lt;!-- Do stuff... --&gt;
+
<?php endwhile; endif; ?>
  <?php endwhile; ?>
+
  
In English the above code would read:
+
日本語ではこのコードはこのように読めます。
  
Set <tt>$my_query</tt> equal to the result of querying all posts where the category is named featured and by the way, get me one post only. Also, set the variable <tt>$do_not_duplicate</tt> equal to the ID number of the single post returned.  Recall that the <tt>Do stuff</tt> line represents all the formatting options associated for the post retrieved.
+
* 表示すべき投稿を取得します。
 +
* 投稿が <tt>$do_not_duplicate</tt> と同じであった場合、何もしません (<tt>continue</tt>)。
 +
* さもなくば、<tt>なにかの処理</tt>にて投稿を表示させます。
 +
* ループの終端処理です。必要に応じて最初に戻るまたは処理を終了します。
 +
この処理は、さらにキャッシュをアップデートすることで、タグとキーワードプラグインが良い働きをするように仕向けます。<tt>$do_not_duplicate</tt> 変数はすでに表示済みな投稿のIDを含むものです。
  
Note that we will need the value of <tt>$do_not_duplicate</tt> in the next step to ensure that the same post doesn't appear in both lists.   
+
<b>最終的な結果</b>
  
<b>Step 2</b>.  The second loop, get the X latest posts (except one).
+
これが<i>フォーマットを含まない</i>コードの最終的な形です。
  
The following code gets X recent posts (as defined in WordPress preferences) save the one already displayed from the first loop and displays them according to <tt>Do stuff</tt>.
+
<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
 +
while ( $my_query->have_posts() ) : $my_query->the_post();
 +
$do_not_duplicate = $post->ID; ?>
 +
&lt;!-- なにかの処理... --&gt;
 +
<?php endwhile; ?>
 +
&lt;!-- 他の処理... --&gt;
 +
<?php if ( have_posts() ) : while ( have_posts() ) : the_post();
 +
if ( $post->ID == $do_not_duplicate ) continue; ?>
 +
&lt;!-- なにかの処理... --&gt;
 +
<?php endwhile; endif; ?>
  
  <?php if (have_posts()) : while (have_posts()) : the_post();
+
この結果は、2つのリストが1つのページに表示されます。最初のリストは 'feature' カテゴリーからの投稿を1つだけ表示し、2つ目のリストは、最初のリストで表示されたものを除いて、WordPress初期設定で定義されたX個の最新投稿が表示されます。そのため、'feature' カテゴリーの投稿が新しいものと置き換えられると、それまで 'feature' カテゴリーから表示されていたものが、通常の投稿リストに表示されます。 (もちろん何個の投稿を表示するかの設定と投稿の頻度に依ります)。この手法は、[[Template_Hierarchy|テンプレート階層]]の知識を組み合わせ、異なった見た目の home.php や index.php を作るために、数多く使われてきています。本ページ末尾にある関連する情報を参照してください。
  if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts); ?>
+
    &lt;!-- Do stuff... --&gt;
+
  <?php endwhile; endif; ?>
+
  
In English the above code would read:
+
<b>最初のカテゴリーの複数投稿に関する注意</b>
  
Get all posts, where a post equals <tt>$do_not_duplicate</tt> then just do nothing (<tt>continue</tt>), otherwise display all the other the posts according to <tt>Do stuff</tt>.  Also, update the cache so the tagging and keyword plugins play nice.  Recall, <tt>$do_not_duplicate</tt> variable contains the ID of the post already displayed.
+
もし、<tt>posts_per_page=2</tt> 以上の設定がある場合、コードを若干修正する必要があります。変数 <tt>$do_not_duplicate</tt> を単独の値から配列に変更する必要があります。さもなくば、最初のループが終わった時点で、<tt>$do_not_duplicate</tt> は最新投稿のIDと同じとなります。その結果、2つ目のループで重複した投稿が表示されることになります。この問題を修正するためには、
  
<b>The End Result</b>
+
<?php $my_query = new WP_Query( 'category_name=featured&amp;posts_per_page=1' );
 +
while ( $my_query->have_posts() ) : $my_query->the_post();
 +
$do_not_duplicate = $post->ID; ?>
  
Here is what the final piece of code looks like <i>without any formatting</i>:
+
  
  <?php $my_query = new WP_Query('category_name=featured&posts_per_page=1');
+
<?php $my_query = new WP_Query( 'category_name=featured&amp;posts_per_page=2' );
  while ($my_query->have_posts()) : $my_query->the_post();
+
while ( $my_query->have_posts() ) : $my_query->the_post();
  $do_not_duplicate = $post->ID;?>
+
$do_not_duplicate[] = $post->ID; ?>
    &lt;!-- Do stuff... --&gt;
+
  <?php endwhile; ?>
+
    &lt;!-- Do other stuff... --&gt;
+
  <?php if (have_posts()) : while (have_posts()) : the_post();
+
  if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts); ?>
+
    &lt;!-- Do stuff... --&gt;
+
  <?php endwhile; endif; ?>
+
  
The end result would be a page with two lists.  The first list contains only one post -- the most recent post from the 'feature' category.  The second list will contain X recent posts (as defined in WordPress preferences) <i>except</i> the post that is already shown in the first list.  So, once the feature post is replaced with a new one, the previous feature will show up in standard post list section below (depending on how many posts you choose to display and on the post frequency).  This technique (or similar) has been used by many in conjunction with knowledge of the [[テンプレート階層|Template Hierarchy]] to create a different look for home.php and index.php.  See associated resources at the bottom of this page.
+
と置き換えてください。
  
<b>Note for Multiple Posts in the First Category</b>
+
この時、<tt>"posts_per_page"</tt> はどんな数字にもなり得ます。
 
+
<tt>$do_not_duplicate</tt> を配列に置き換えた後は、
If posts_per_page=2 or more, you will need to alter the code a bit.  The variable $do_not_duplicate needs to be changed into an array as opposed to a single value.  Otherwise, the first loop will finish and the variable $do_not_duplicate will equal only the id of the latest post.  This will result in duplicated posts in the second loop.  To fix the problem replace
+
 
   
 
   
  <?php $my_query = new WP_Query('category_name=featured&amp;posts_per_page=1');
+
  <?php if ( have_posts() ) : while ( have_posts() ) : the_post();  
  while ($my_query->have_posts()) : $my_query->the_post();
+
if ( $post->ID == $do_not_duplicate ) continue; ?>
  $do_not_duplicate = $post->ID;?>
+
  
with
+
  
  <?php $my_query = new WP_Query('category_name=featured&amp;posts_per_page=2');
+
  <?php if ( have_posts() ) : while ( have_posts() ) : the_post();  
  while ($my_query->have_posts()) : $my_query->the_post();
+
if ( in_array( $post->ID, $do_not_duplicate ) ) continue; ?>
  $do_not_duplicate[] = $post->ID ?>
+
  
Note that "posts_per_page" can be any number.
+
としてください。これで、<tt>"posts_per_page"</tt> がどんな値でも (この場合は2ですが) このパターンを続けることが出来ます。
This changes $do_not_duplicate into an array.  Then replace
+
+
<?php if (have_posts()) : while (have_posts()) : the_post(); if( $post->ID ==
+
  $do_not_duplicate ) continue; update_post_caches($posts); ?>
+
  
with
+
一方で、<tt>$do_not_duplicate</tt> の配列をまるごと <tt>$wp_query</tt> に渡し、条件を満たしたもののみ返すというやり方もできます。
  
  <?php if (have_posts()) : while (have_posts()) : the_post();
+
  <?php query_posts( array( 'post__not_in' => $do_not_duplicate ) );
  if (in_array($post->ID, $do_not_duplicate)) continue;
+
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>  
  update_post_caches($posts); ?>
+
  
Where you continue the pattern for whatever posts_per_page is set equal to (2 in this case).
+
文字列の代わりに、 <tt>post__not_in</tt> オプションを用いることで、クエリーのパラメーターが配列となります。
  
Alternatively you can pass the entire <tt>$do_not_duplicate</tt> array to <tt>$wp_query</tt> and only entries that match your criteria will be returned:
+
<div id="Nested Loops">
+
<?php query_posts(array('post__not_in'=>$do_not_duplicate));
+
  if (have_posts()) : while (have_posts()) : the_post();
+
  update_post_caches($posts); ?>  
+
  
Note that instead a string, the query parameter was an associative array, with <tt>post__not_in</tt> option.
+
== 入れ子のループ ==
 +
</div>
 +
入れ子のループとは、最初のループが終わる前に2つ目のループを実行することを意味します。これは[[Shortcode API|ショートコード]]を用いた投稿リストを作成する時に役立ちます。例えば:
  
===ソース===
+
<code>
This article on multiple loops is a combination of [http://boren.nu Ryan Boren] and [http://www.alexking.org Alex King's] [http://comox.textdrive.com/pipermail/hackers/2005-January/003578.html discussion] about the Loop on the [[Mailing Lists#Hackers|Hackers Mailing List]] as well as the tutorial written at [http://www.maxpower.ca/wordPress-hack-sticky-adhesive-kubrick/2005/05/03/ MaxPower].
+
$my_query = new WP_Query( 'cat=3' );
 +
if ( $my_query->have_posts() ) {
 +
while ( $my_query->have_posts() ) {
 +
$my_query->the_post();
 +
the_content();
 +
}
 +
}
 +
wp_reset_postdata();
 +
</code>
  
==その他のループ関連リソース==
+
入れ子のループが終わった後、いくつかのグローバル変数が正しい値を再度取得することが出来るようにするために、メインループのデータをリセットする必要があります。
  
To learn more about the WordPress Loop, and the various template tags that work only within the Loop, here are more resources.
+
<div id="Sources">
 +
===ソース===
 +
</div>
 +
複数ループの章で取り上げられた内容は、[http://boren.nu Ryan Boren] と [http://www.alexking.org Alex King's] が [[Mailing Lists#Hackers|開発者メーリングリスト]]で行った、ループに関する[http://comox.textdrive.com/pipermail/hackers/2005-January/003578.html 議論]の組み合わせです。
 +
入れ子ループの例は、メーリングリストでの[http://lists.automattic.com/pipermail/wp-hackers/2010-May/032064.html 別の議論]から着想し、 [http://www.nkuttler.de/2010/05/30/wordpress-loop-inside-a-loop/ Nicolas Kuttler] が投稿したものです。
  
* [[The_Loop_in_Action|ループの使用例]]/[[:en:The_Loop_in_Action|en]]
+
<div id="More Loop Resources">
* [[テンプレートタグ]]
+
* [[テンプレート|ループをテンプレートファイル内で使う]]
+
  
===リソース===
+
==リソース==
 +
</div>
 +
==== 英語 ====
 +
* [http://generatewp.com/wp_query/ WordPress WP_Query Generator]
 +
* [http://www.slideshare.net/mitcho/getting-into-the-loop Getting Into The Loop] - (slides) an introduction to how plugins and themes can modify the Loop
 +
* [http://web-profile.com.ua/wordpress/themes/wordpress-custom-loop/ WordPress custom loop]
  
 
==== 日本語 ====
 
==== 日本語 ====
338行目: 389行目:
 
* [http://tech.ludicmind.net/cms/wordpress/wordpress_1.html WordPressループの使用方法 (tech.ludicmind.net)]
 
* [http://tech.ludicmind.net/cms/wordpress/wordpress_1.html WordPressループの使用方法 (tech.ludicmind.net)]
 
* [http://www.findxfine.com/wordpress/528.html ループ : WordPress (FindxFine)]
 
* [http://www.findxfine.com/wordpress/528.html ループ : WordPress (FindxFine)]
 +
 +
 +
<div id="Related">
 +
==関連==
 +
</div>
 +
 +
WordPressループについて、またループ内で使える様々なテンプレートタグについて更に詳しくは、下記のリソースを参照してください。
 +
 +
===ループについての詳細===
 +
* [[The_Loop_in_Action|ループの使用例]]
 +
* [[テンプレートタグ]]
 +
* [[テンプレート|ループをテンプレートファイル内で使う]]
 +
  
 
==== 英語 ====
 
==== 英語 ====
347行目: 411行目:
 
* [http://rhymedcode.net/1001-wordpression-loops/ 1001 WordPression Loops]
 
* [http://rhymedcode.net/1001-wordpression-loops/ 1001 WordPression Loops]
  
{{原文|The Loop|89201}} <!-- 2010-05-29T18:44:24 Lloydbudd 版 -->
+
 
 +
{{Query Tags}}
 +
 
 +
{{原文|The Loop|152002}} <!-- 14:15, 10 June 2015‎ Webvitaly 版 -->
  
 
{{DEFAULTSORT:るうふ}}
 
{{DEFAULTSORT:るうふ}}
 +
[[Category:WordPress レッスン]]
 
[[Category:デザインとレイアウト]]
 
[[Category:デザインとレイアウト]]
 
[[Category:テンプレート]]
 
[[Category:テンプレート]]

2021年9月6日 (月) 15:11時点における最新版


このページは最新情報に追随して更新されていません。英語版のテーマハンドブックコードリファレンスをご確認ください。翻訳にご協力くださる方はぜひご相談ください


ループ」は、WordPress の投稿を表示するために使われるPHPコードです。このループを使えば、現在のページに表示される各投稿を処理したり、ループタグ内で指定された条件に沿って投稿の形式を整えたりできます。ループの開始部分と終了部分の間に書きこんだ HTMLPHP のコードは、各投稿の表示に使われます。

テンプレートタグプラグインの説明内に「このタグ(プラグイン)はループ内で使います」とある場合、タグが各投稿で繰り返して表示されます。例として、以下が各投稿にデフォルトでループ内に含まれます。

さらに他のテンプレートタグを使ったり、詳しい人ならば $post 変数にアクセスしたりして、投稿に関する様々な情報を表示することもできます。

ループに始めて触れる人は、ループの使用例/en ページも参照してください。

ループの使い方

ループは index.php などのテンプレートファイルに含め、投稿の情報を表示するために使います。

テーマのテンプレートの最初で、ヘッダーテンプレートを必ず呼び出すようにしてください。もしループをテンプレート以外の自分のデザインで使っている場合、WP_USE_THEMESfalse に設定します。

<?php define( 'WP_USE_THEMES', false ); get_header(); ?>

ループはここから始まり、

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

ここで終わります。

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

PHPの制御構造を用いることで、このような表現も可能です。

<?php 
if ( have_posts() ) {
	while ( have_posts() ) {
		the_post(); 
		//
		// 投稿がここに表示される
		//
	} // end while
} // end if
?>

ループの例

特定のカテゴリーにある投稿のスタイルを変更する

以下のコードは各投稿をのタイトル (パーマリンクとして用いられるもの)、カテゴリー、内容を表示するものです。これはまた、in_category() テンプレートタグを使ってカテゴリー番号が3の投稿に他とは別のCSSクラス名を割り当てています。CSS(style.css)内でこのクラスの宣言を追加・編集することにより、カテゴリー3の投稿にのみ特別なスタイルを加えることができます。

<!-- --> というHTMLコメントで囲まれた部分は、実際にブラウザでは表示されません。ここではコードを分かりやすくするためにHTMLコメントで囲んだ説明を挿入していますが、実際にはテンプレート内に書き込まなくてもかまいません。

 <!-- ループ開始 -->
 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

 <!-- 以下で、投稿がカテゴリー3に属しているかテスト -->
 <!-- もし属している場合、"post-cat-three"というCSSクラスのdivボックスを表示 -->
 <!-- それ以外の場合、"post"というCSSクラスのdivボックスを表示 -->
 <?php if ( in_category( '3' ) ) : ?>
 	<div class="post-cat-three">
 <?php else : ?>
 	<div class="post">
 <?php endif; ?>

 <!-- 投稿のタイトルとパーマリンクを表示 -->
 <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>

 <!-- 日時を表示 -->
 <small><?php the_time('F jS, Y'); ?></small>

 <!-- 投稿の本文をdiv内に表示 -->
 <div class="entry">
  <?php the_content(); ?>
 </div>

 <!-- 投稿のカテゴリーをコンマ区切りで表示 -->
 <p class="postmetadata">Posted in <?php the_category(', '); ?></p>
 </div> <!-- 最初の div ボックスを閉じる -->

 <!-- “else”部分を除いたループ終了 -->
 <?php endwhile; else: ?>

 <!-- 最初の“if”にて表示する投稿があるかどうかをテストしたため、“else”では投稿がない場合に実行 -->
 <!-- つまり、投稿がなければ以下を表示 -->
 <p>Sorry, no posts matched your criteria.</p>

 <!-- ループを「完全に」終了 -->
 <?php endif; ?>

注: HTMLコードをテンプレート内に書く場合は、必ず <?php  ?> というPHP開始・終了タグの外側に書かなければなりません。逆に、PHPコードは、必ず <?php  ?> タグの内側に書きます。上記のように、ifelse ステートメント内でもPHPコードを一時的に閉じ、HTMLコードを書くことができます。

特定カテゴリーの投稿を除外する

この例は特定のカテゴリーを表示させない場合を示します。この場合、カテゴリー3と8の投稿を除外します。この例は上記の例とは異なり、クエリー自身を変更しています。

 <?php $query = new WP_Query( 'cat=-3,-8' ); ?>
 <?php if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); ?>

 <div class="post">
 
 <!-- Display the Title as a link to the Post's permalink. -->
 <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>

 <!-- Display the date (November 16th, 2009 format) and a link to other posts by this posts author. -->
 <small><?php the_time( 'F jS, Y' ); ?> by <?php the_author_posts_link(); ?></small>
 
  <div class="entry">
  	<?php the_content(); ?>
  </div>

  <p class="postmetadata"><?php _e( 'Posted in' ); ?> <?php the_category( ', ' ); ?></p>
 </div> <!-- closes the first div box -->

 <?php endwhile; 
 wp_reset_postdata();
 else : ?>
 <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
 <?php endif; ?>


: この例をメインページに用いる場合、違うテンプレートカテゴリーページに適用させる必要があります。さもなくば、WordPressは、カテゴリーアーカイブを含めた全てのページから、カテゴリー3と8の投稿を除外してしまいます。しかし、同じテンプレートファイルを使いたい場合、is_home() タグを用いることで、カテゴリー3と8の投稿がメインページからのみ除外されるようにすることができます。

...
<?php if ( is_home() ) {
$query = new WP_Query( 'cat=-3,-8' );
if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); 
} else {
...
?>
...

他にも条件分岐タグを用いることで、ページに対する特定の条件がtrueであるか否かで出力をコントロールすることができます。

複数のループ

この章ではループの発展的用途について解説します。少々技術的な内容ですが、怖がらずに読んでください。簡単なところから徐々に発展した内容に入っていきます。ほんの少しの常識や我慢、そして熱意があれば、あなたも複数のループを使うことが出来るでしょう。

はじめに、「なぜ複数のループが必要なのか?」という点について考えてみましょう。おそらくあなたは何かをある投稿のグループに対して行い、別の何かを他の投稿のグループに対して行ったものの、同じページが両方のグループに表示されてしまったのでしょう。「何か」というのは「何にでも」という事になり得ます。あなたは今、PHPのスキルと想像に縛られています。

では、例に入りましょう。まずは普通のループから。

<?php if ( have_posts() ) : ?>
	<?php while ( have_posts() ) : the_post(); ?>    
	<!-- なにかの処理 ... -->
	<?php endwhile; ?>
<?php endif; ?>


(ソースコードを読むのに慣れている人は飛ばして下さい)。 これを日本語で言えば、以下の様になります。

  • もし投稿を表示できれば、次へと進む。
  • そして一覧に存在している投稿ごとそれぞれに、
  • <!-- なにかの処理 ... -->を行う。
  • 最後の投稿にたどり着いたら、終了する。

ここでの <!-- なにかの処理 ... --> はテンプレートに依存します。

なにかの処理について: この例ではページの各投稿をどうフォーマットし、どう表示させるかというコード一式を表しています。ここに入るコードはWordPressでどう表現したいかに依って異なります。例えば、Kubrickのテーマの index.php を見た場合、

<?php while ( have_posts() ) : the_post(); ?>

に続いて、この行が入ります。

<?php comments_popup_link( 'No Comments »', '1 Comment »', '% Comments »' ); ?>

コーダー向けの説明: have_posts()the_post() は、全てのアクションであるグローバルな $wp_query オブジェクトを用いるのに便利なラッパーです。$wp_query はブログのヘッダーで呼び出され、GETPATH_INFO を通して来たクエリー引数が入力されます。$wp_query は引数を受け、ビルドし、データベースクエリーを実行し、投稿の配列を作成します。この配列はオブジェクト内に格納され、またグローバルの$posts 配列の中に (古い投稿ループとの後方互換性のために) 入っているブログのヘッダーに返されます。

WordPressがブログのヘッダーを読み込み終わり、テンプレートまでたどり着くと、投稿のループに到達します。ここで have_posts()$wp_query->have_posts()を呼び出し、ループカウンターと投稿配列に残った投稿の有無をチェックします。そしてthe_post()$wp_query->the_post() を呼びだし、ループカウンターを進め、グローバルの $post 変数と、全てのグローバル投稿データをセットアップします。ループが完了したら、have_posts() がfalseを返し、終了します。

ループの例

以下に複数ループの使用例を2つ示します。複数ループを使うための鍵は $wp_query が一度しか呼び出されないところにあります。これを回避するために、 rewind_posts() を呼び出してクエリーを再利用するか、新しいクエリーオブジェクトを生成します。これは複数ループの例 1の内容です。複数ループの例 2ではクエリーの結果を格納する変数を使うケースがを挙げています。最後に複数ループの使い方では、ブログのホームページに特定のカテゴリーの投稿を優先的に載せるために様々なアイディアを駆使した複数ループの使用方法の1つを記載しています。

複数ループの例 1

二度目のループでも同じ様に処理を行うにはrewind_posts()を呼び出して下さい。 この関数はループのカウンタをリセットし、別のループを実行出来るようにします。

<?php rewind_posts(); ?>
 
<?php while ( have_posts() ) : the_post(); ?>
	<!-- なにかの処理... -->
<?php endwhile; ?>

もし既に標準のクエリに関するループを終了したあと、別のクエリを使いたくなったら、$wp_queryオブジェクトをquery_posts()から呼び出すことが可能です。query_posts()は新しいクエリ、投稿リストを作り、ループをリセットします。

// special_cat カテゴリーから10件の投稿を取り出します。
<?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( have_posts() ) : the_post(); ?>
	<!-- special_cat についての処理... -->
<?php endwhile; ?>

もし標準のクエリを保持しておきたければ、新しいクエリオブジェクトを生成するという方法があります。

<?php $my_query = new WP_Query( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
	<!-- special_cat についての処理.... -->
<?php endwhile; ?>


$wp_query用のhave_posts()the_post() が使えないので、新たなオブジェクト my_query を生成します。 (訳注: ただの have_posts()the_posts() ではなく、事前に生成した $my_query のメソッドであることに注意して下さい。)

複数ループの例 2

複数ループを使うもう一つの方法は、have_posts()the_post() が使えないことに対する別の回避策を必要とします。これを解決するために、オリジナルのクエリー結果を変数に格納し、もう一方のループで再度割り当てる必要があります。これにより、全てのグローバルに依存する全ての標準機能を使うことができます。

例:

// ここで脇にそれる
<?php $temp_query = $wp_query; ?>
<!-- なにかの処理... -->

<?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( have_posts() ) : the_post(); ?>
	<!-- special_cat についての処理... -->
<?php endwhile; ?>
// ここで通常のプログラミングに戻る
<?php $wp_query = $temp_query; ?>

注: PHP 4では "=" オペレーターでオブジェクトが参照されていましたが、PHP 5では "= clone" オペレーターで参照されます。例 2をPHP 5で動くようにするためには、以下のコードを用いる必要があります。

 // ここで脇にそれる
 <?php $temp_query = clone $wp_query; ?>
 <!-- Do stuff... -->
 
 <?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>
 
 <?php while ( have_posts() ) : the_post(); ?>
 	<!-- special_cat についての処理... -->
 <?php endwhile; ?>
 <?php endif; ?>
 
 // ここで通常のプログラミングに戻る
 <?php $wp_query = clone $temp_query; ?>

しかし、2つ目の例はWordPress 2.1では使うことはできません。

複数ループの使い方

複数ループをどのように使うかを理解するための最適な方法は、その使用例を見せることです。最も一般的な複数ループの使い方は、2つ以上の投稿リストを1つのページに表示させることです。最新の投稿だけでなく、特定のカテゴリーからの投稿も注目させたい時にしばしば使われ方法です。

フォーマットとCSSに関する全ての問題は一旦脇において、2つの投稿リストを表示させたい場合を考えましょう。1つは最新の投稿 (標準的な最新10件の投稿)、もう1つは 'featured' カテゴリーからの最新投稿を1件だけを表示させるとします。'featured' カテゴリーからの投稿を一番最初に表示し、次に投稿のリスト (標準のもの) という順番で考えます。重要なのは、両方のカテゴリーに表示させる投稿はあってはならないというところです。

ステップ 1. ‘featured’ カテゴリーから1つの投稿だけを取得する。

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
	<!-- なにかの処理... -->
<?php endwhile; ?>


日本語ではこのコードはこのように読めます。

  • $my_query は 'featured' と名付けられたカテゴリーからの全ての投稿を検索します。ただし、最新の投稿1件分だけ貰います。
  • そして一覧に存在している投稿ごとそれぞれに (この場合は1件ですが)
  • $do_not_duplicate という変数を、1行目で返された投稿のIDで設定します。
  • なにかの処理というのは、表示される投稿に関する全てのフォーマットオプションの処理です。
  • ループを終了します (この場合は1件ですが)

この時大事なのは、同じ投稿が2つのリストに出ないようにするために、 $do_not_duplicate の値が次のステップで必要とされることです。

ステップ 2. 2つ目のループで、X個の最新投稿を取得する (但し、1つを除く)

以下のコードでは、WordPress初期設定で定義されたX個の最新投稿を取得し、最初のループで保存された表示済みの投稿をセーブし、なにかの処理に従って表示させます。

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue;?>
	<!-- なにかの処理... -->
<?php endwhile; endif; ?>

日本語ではこのコードはこのように読めます。

  • 表示すべき投稿を取得します。
  • 投稿が $do_not_duplicate と同じであった場合、何もしません (continue)。
  • さもなくば、なにかの処理にて投稿を表示させます。
  • ループの終端処理です。必要に応じて最初に戻るまたは処理を終了します。

この処理は、さらにキャッシュをアップデートすることで、タグとキーワードプラグインが良い働きをするように仕向けます。$do_not_duplicate 変数はすでに表示済みな投稿のIDを含むものです。

最終的な結果

これがフォーマットを含まないコードの最終的な形です。

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
	<!-- なにかの処理... -->
<?php endwhile; ?>
	<!-- 他の処理... -->
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue; ?>
	<!-- なにかの処理... -->
<?php endwhile; endif; ?>

この結果は、2つのリストが1つのページに表示されます。最初のリストは 'feature' カテゴリーからの投稿を1つだけ表示し、2つ目のリストは、最初のリストで表示されたものを除いて、WordPress初期設定で定義されたX個の最新投稿が表示されます。そのため、'feature' カテゴリーの投稿が新しいものと置き換えられると、それまで 'feature' カテゴリーから表示されていたものが、通常の投稿リストに表示されます。 (もちろん何個の投稿を表示するかの設定と投稿の頻度に依ります)。この手法は、テンプレート階層の知識を組み合わせ、異なった見た目の home.php や index.php を作るために、数多く使われてきています。本ページ末尾にある関連する情報を参照してください。

最初のカテゴリーの複数投稿に関する注意

もし、posts_per_page=2 以上の設定がある場合、コードを若干修正する必要があります。変数 $do_not_duplicate を単独の値から配列に変更する必要があります。さもなくば、最初のループが終わった時点で、$do_not_duplicate は最新投稿のIDと同じとなります。その結果、2つ目のループで重複した投稿が表示されることになります。この問題を修正するためには、

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=2' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate[] = $post->ID; ?>

と置き換えてください。

この時、"posts_per_page" はどんな数字にもなり得ます。 $do_not_duplicate を配列に置き換えた後は、

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue; ?>

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( in_array( $post->ID, $do_not_duplicate ) ) continue; ?>

としてください。これで、"posts_per_page" がどんな値でも (この場合は2ですが) このパターンを続けることが出来ます。

一方で、$do_not_duplicate の配列をまるごと $wp_query に渡し、条件を満たしたもののみ返すというやり方もできます。

<?php query_posts( array( 'post__not_in' => $do_not_duplicate ) );
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> 

文字列の代わりに、 post__not_in オプションを用いることで、クエリーのパラメーターが配列となります。

入れ子のループ

入れ子のループとは、最初のループが終わる前に2つ目のループを実行することを意味します。これはショートコードを用いた投稿リストを作成する時に役立ちます。例えば:

$my_query = new WP_Query( 'cat=3' );
if ( $my_query->have_posts() ) { 
	while ( $my_query->have_posts() ) { 
		$my_query->the_post();
		the_content();
	}
}
wp_reset_postdata();

入れ子のループが終わった後、いくつかのグローバル変数が正しい値を再度取得することが出来るようにするために、メインループのデータをリセットする必要があります。

ソース

複数ループの章で取り上げられた内容は、Ryan BorenAlex King's開発者メーリングリストで行った、ループに関する議論の組み合わせです。 入れ子ループの例は、メーリングリストでの別の議論から着想し、 Nicolas Kuttler が投稿したものです。

リソース

英語

日本語


WordPressループについて、またループ内で使える様々なテンプレートタグについて更に詳しくは、下記のリソースを参照してください。

ループについての詳細


英語


記事

コード・ドキュメンテーション

  • クラス: WP_Query - WP_Query クラスの詳細な全容
  • クラス: WP_Comment_Query - コメント関連のクエリのためのクラス
  • クラス: WP_User_Query - ユーザー関連のクエリのためのクラス
  • オブジェクト: $wpdb - $wpdb オブジェクトの使い方全容
  • 関数: set_query_var()
  • 関数: get_query_var()
  • 関数: query_posts() - 追加のカスタムクエリを作成
  • 関数: get_post() - 項目の ID を取得しデータベース内にあるその投稿のレコードを返す
  • 関数: get_posts() - 投稿の配列を返すことに特化した関数
  • 関数: get_pages() - ページの配列を返すことに特化した関数
  • 関数: have posts() - クエリが投稿を返すか否かを判断する条件関数
  • 関数: the_post() - クエリ後に自動的にループを設定する
  • 関数: rewind_posts() - 現状のループをリセットする
  • 関数: setup_postdata() - ループ内で個別の結果を得るためのクエリデータを設定する
  • 関数: wp_reset_postdata() - 直前のクエリを復元する (通常はループ内の別のループの後に用いられる)
  • 関数: wp_reset_query()
  • 関数: is_main_query() - 変更されるクエリがメインのクエリであることを確認する
  • アクションフック: pre_get_posts - WordPressクエリが実行される前に変更する
  • アクションフック: the_post - post クエリの後で post オブジェクトを変更する
  • フィルターフック: found_posts - WP_Query オブジェクトの found_posts 値を変更する


最新英語版: WordPress Codex » The Loop最新版との差分