ループ

2020.04.01 2020.04.02

TOPICS

翻訳元記事はこちらです。

ループとは、WordPressがテーマのテンプレートファイルを介して投稿を出力するために使用するデフォルトの仕組みです。
どれだけの投稿を取得するかは、管理画面の表示設定で「1ページに表示する最大投稿数」の設定によります。
ループ内では、WordPress は現在のページに表示される各投稿を取得し、テーマの指示に従ってフォーマットします。

ループは WordPress のデータベースから各投稿のデータを抽出し、各テンプレートタグの代わりに適切な情報を挿入します。ループ内の任意のHTMLまたはPHPコードは、各投稿に対して処理されます。

簡単に言うと、ループはその名の通り、現在のページで取得した各記事を一度にループし、テーマで指定したアクションを実行します。

以下の例のように、ループは様々な用途で使用できます。

テンプレートファイル全体でループをカスタマイズして、異なるコンテンツを表示したり操作したりすることができます。

ループの詳細

基本的なループの例です。

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // Display post content
    endwhile; 
endif; 
?>

このループは、投稿があるときはループして投稿を表示します。さらに詳しく分解してみます。

ループの使い方

ループは index.php や、投稿情報を表示するために使用される他のテンプレートの中に配置しなければなりません。ヘッダーを何度も重複させたくないので、ループは常に get_header() の呼び出しの後に配置する必要があります。例えば、以下のようになります。

<?php 
get_header();
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        // Display post content
    endwhile; 
endif; 
?>

上記の例では、ループの終わりをendwhileとendifで示しています。ループは、上述したように、常に同じif文とwhile文で始まり、同じend文で終わらなければなりません。

すべての投稿に適用したいテンプレートタグは、ループの間に書く必要があります。

指定した条件に一致する投稿がない場合に表示されるカスタム404「見つかりませんでした」メッセージを含めることができます。
以下の例のように、メッセージはendwhileendifの間に配置する必要があります。

非常にシンプルなindex.phpファイルは次のようになります。

<?php
get_header();
 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_content();
    endwhile;
else :
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' );
endif;
 
get_sidebar();
get_footer();
?>

ループで表示できるもの

ループは、各投稿に対して多くの要素を表示することができます。例えば、多くのテーマで使用されている一般的なテンプレートタグは以下の通りです。

next_post_link()現在の投稿の後に、公開済みの投稿へのリンク
previous_post_link()現在の投稿の前に、公開済みの投稿へのリンク
the_category()表示されている投稿やページに関連するカテゴリ
the_author()投稿やページの著者
the_content()投稿やページの内容
the_excerpt()省略記号(…)が続く投稿のメインコンテンツの最初の55語、または記事全体を読むためのリンクです。また、投稿の「抜粋」フィールドを使用して、特定の抜粋の長さをカスタマイズすることもできます。
the_ID()投稿やページのID
the_meta()投稿やページに関連するカスタムフィールド
the_shortlink()サイトのURLと投稿やページのIDを使用したページや投稿へのリンク
the_tags()投稿やページに関連するタグ
the_title()投稿やページのタイトル
the_time()投稿やページの日付や時刻を表示します。これは、標準の php date関数の書式を使用してカスタマイズすることができます。

以下のような条件付きタグも使用できます。

is_home()現在のページが、ホームページの場合は、trueを返す
is_admin管理画面の場合は、trueを返す
is_single()個別ページの場合は、trueを返す
is_page()固定ページの場合は、trueを返す
is_page_template()ページが特定のテンプレートを使用しているかどうかを判断するために使用することができます。
例:is_page_template('about-page.php')
is_category()ページ、投稿が特定のカテゴリーを使用していれば、trueを返します。
例:is_category('news')
is_tag()ページ、投稿が特定のタグを使用していれば、trueを返します。
is_author()著者のアーカイブページの場合はtrueを返します
is_search()検索結果ページの場合は、trueを返します
is_404()404ページの場合は、trueを返します
has_excerpt()投稿、ページに抜粋文があれば、trueを返します

ループの使用例を見てみましょう。

基本的な例

ブログのアーカイブ

ほとんどのブログにはブログアーカイブページがあり、そこには投稿タイトル、サムネイル、抜粋などを表示することができます。下の例は、投稿があるかどうかをチェックし、投稿がある場合は各投稿のタイトル、サムネイル、抜粋を出力する簡単なループを示しています。存在しない場合は、カッコの中のメッセージが表示されます。

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        the_title( '<h2>', '</h2>' ); 
        the_post_thumbnail(); 
        the_excerpt();
    endwhile; 
else: 
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); 
endif; 
?>

個別投稿ページ

WordPressでは、各投稿には個別のページがあり、その投稿に関連する情報が表示されます。テンプレートタグを使って、どの情報を表示するかをカスタマイズすることができます。

下の例では、ループは記事のタイトルと内容を出力しています。この例を投稿や固定ページのテンプレートファイルに使用して、投稿に関する最も基本的な情報を表示することができます。また、このテンプレートをカスタマイズして、カテゴリなどのデータを投稿に追加することもできます。

<?php 
if ( have_posts() ) : 
    while ( have_posts() ) : the_post(); 
        the_title( '<h1>', '</h1>' ); 
        the_content();
    endwhile; 
else: 
    _e( 'Sorry, no pages matched your criteria.', 'textdomain' ); 
endif; 
?>

中級の例

それぞれのカテゴリーで異なるスタイルを適用する

以下の例では、いくつかのことを行っています。

この例のコードのコメントでは、ループの各段階で詳細を説明しています。

<?php
// Start the Loop.
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        /** 現在の投稿のカテゴリーIDが3の場合、
          * divタグに"post-category-three"クラスを適用します。
          * それ以外の場合は、"post"クラスを適用します。
          */
        if ( in_category( 3 ) ) : ?>
        <div class="post-category-three">
        <?php else : ?>
        <div class="post">
        <?php endif; 
 
            // Display the post's title.
            the_title( '<h2>', ';</h2>' ); 
 
            // Display a link to other posts by this posts author.
            printf( __( 'Posted by %s', 'textdomain' ), get_the_author_posts_link() );
 
            // Display the post's content in a div.
            ?>
            <div class="entry">
                <?php the_content() ?>
             </div>
     
            <?php
            // Display a comma separated list of the post's categories.
            _e( 'Posted in ', 'textdomain' ); the_category( ', ' ); 
 
        // closes the first div box with the class of "post" or "post-cat-three"
       ?>
       </div>
 
    <?php 
    // Stop the Loop, but allow for a "if not posts" situation
    endwhile; 
 
else :
    /*
      * The very first "if" tested to see if there were any posts to
      * display. This "else" part tells what do if there weren't any.
     */
     _e( 'Sorry, no posts matched your criteria.', 'textdomain' );
  
// Completely stop the Loop.
 endif;
?>

複数のループ

状況によっては、複数のループを使用する必要があるかもしれません。
例えば、投稿のタイトルをページの上部にあるコンテンツリストの表に表示し、ページの下の方にコンテンツを表示したい場合などです。クエリは変更されないので、2回目に投稿をループさせる必要があるときにループを巻き戻す必要があります。そのために関数 rewind_posts() を使用します。

rewind_posts()の使い方

rewind_posts() を使用すると、同じクエリを2回ループさせることができます。これは、同じクエリをページ上の異なる場所に二度表示させたい場合に便利です。

以下に rewind_posts() の使用例を示します。

<?php
// Start the main loop
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_title();
    endwhile;
endif;
 
// Use rewind_posts() to use the query a second time.
rewind_posts();
 
// Start a new loop
while ( have_posts() ) : the_post();
    the_content();
endwhile;
?>

2つ目のクエリとループ

同じクエリで2つのループを使うのは比較的簡単でしたが、必ずしも必要なものとは限りません。
その代わりに、テンプレート上に異なるコンテンツを表示するために2つ目のクエリを作成したい場合が多いでしょう。
例えば、同じページに2つのグループの投稿を表示したいが、それぞれのグループに対して異なる処理をしたいとします。よくある例としては、以下のように、1つの投稿の下に同じカテゴリの投稿のリストを表示することがあります。

<?php
// The main query.
if ( have_posts() ) : 
    while ( have_posts() ) : the_post();
        the_title();
        the_content();
    endwhile;
else :
    // When no posts are found, output this text.
    _e( 'Sorry, no posts matched your criteria.' );
endif;
wp_reset_postdata();                                                        
 
/*
 * The secondary query. Note that you can use any category name here. In our example,
 * we use "example-category".
 */
$secondary_query = new WP_Query( 'category_name=example-category' );        
 
// The second loop. 
if ( $secondary_query->have_posts() )
    echo '<ul>';
    while ( $secondary_query->have_posts() ) : $secondary_query->the_post();
        the_title( '<li>', '</li>' );
     endwhile;
     echo '</ul>';
endif;
wp_reset_postdata();
?>

上の例でわかるように、まず通常のループを表示します。次に、WP_Queryを使用して特定のカテゴリ(例では、example-category)を取得するための新しい変数を定義します。

上の例の通常のループには1つ違いがあることに注意してください。それは、投稿データをリセットするために wp_reset_postdata() を呼び出していることです。
2 番目のループを使う前に、投稿データをリセットする必要があります。これには以下の2つの方法があります。

  1. rewind_posts() 関数を使用する
  2. 新しいクエリオブジェクトを作成する

複数のループをリセットする

テンプレートで複数のループを使用する場合は、それらをリセットすることが重要です。そうしないと、データがどのように保存され、グローバル変数$post内で使用されるかによって、予期しない結果を招く可能性があります。ループをリセットするには、呼び出し方によって主に3つの方法があります。

wp_reset_postdata()の使い方

WP_Queryでカスタムループや複数ループを実行している場合は、wp_reset_postdata()を使用します。この関数は、グローバルな $post 変数をメインクエリの現在の投稿にリストアします。ベストプラクティスに従っていれば、これはループをリセットするために使用する最も一般的な関数です。

この関数を適切に使用するには、WP_Queryを使用した任意のループの後に以下のコードを配置します。

<?php wp_reset_postdata(); ?>

wp_reset_postdata()でリセットするWP_Queryを使ったループの例です。

<?php 
// Example argument that defines three posts per page. 
$args = array( 'posts_per_page' => 3 ); 
 
// Variable to call WP_Query. 
$the_query = new WP_Query( $args ); 
 
if ( $the_query->have_posts() ) : 
    // Start the Loop 
    while ( $the_query->have_posts() ) : $the_query->the_post(); 
        the_title(); 
        the_excerpt(); 
    // End the Loop 
    endwhile; 
else: 
// If no posts match this query, output this text. 
    _e( 'Sorry, no posts matched your criteria.', 'textdomain' ); 
endif; 
 
wp_reset_postdata(); 
?>

wp_reset_query()の使い方

wp_reset_query() を使用すると、WP_Query とグローバルな $post データを元のメインクエリに戻します。
ループ内で query_posts() を使用している場合は、この関数を使用してループをリセットしなければなりません。
WP_Queryを使ったカスタムループの後にこの関数を使うこともできますが、これは実行時に実際にwp_reset_postdata()を呼び出すからです。
しかし、WP_Query が関与するカスタムループでは wp_reset_postdata() を使用するのがベストプラクティスです。

query_posts() はベストプラクティスではないので、可能な限り避けるべきです。そのため、wp_reset_query() はあまり使うべきではありません。

この関数を適切に使用するには、 query_posts() を使用したループの後に以下のコードを配置します。

<?php wp_reset_query(); ?>