ヘッダーのロゴ

すぐに仕事で使えるIT技術情報メディア

完全解説!WordPressループとは?メインループからサブループまで徹底解説

投稿日:2024年04月21日(日) 更新日:2024年06月27日(木)
完全解説!WordPressループとは?メインループからサブループまで徹底解説|WordPress MAGAZINE ワードプレスマガジン|すぐに仕事で使えるIT技術情報メディア

みなさんこんにちは!エンジニアの高澤です!

今回はWordPressループであるメインループからサブループについて解説していきたいと思います。

WordPressループはWordPress構築において基本中の基本の技術になり、エンジニアにとっては必ず扱えなければならない技術になります。

その理由は、WordPressループが扱えなければテーマ開発やプラグイン開発に対応することができないからです。

よろしければぜひ当記事をお役立ていただけましたら幸いです。

WordPressループとは

WordPressループとは、記事データを一覧で表示させたり記事の詳細ページの本文コンテンツを表示したりする際に使用するPHPのループ文のことをいいます。

具体的には、PHPの制御構文であるwhile文やforeach文などの繰り返しループ処理系の構文を使って、データベースにある記事コンテンツデータを出力するコードのことをいいます。

このWordPressループは以下のように2種類あります。

  • メインループ
  • サブループ

それぞれ解説いたします。

メインループとは

メインループとは、WordPressで最も基本になる処理になります。

WordPressのテーマ開発において中心的な役割を果たす、投稿記事ページなどのコンテンツを取得し、表示するための基本的なループのことです。

WordPressのテーマファイル内で使用され、投稿のタイトルや本文などのコンテンツを取り出して表示します。

注意点としては一度のページ表示でメインループを使えるのは一回のみです。(この後解説する「サブループ」は何回でも使えます)

それでは具体的にメインループのコードを見てイメージを掴みましょう。

記事一覧系のメインループ

以下のコードは、index.phpやcategory.php、archive.phpなどの記事一覧を表示するPHPテンプレートファイルに記述するコードの雛形になります。

<?php
if (have_posts()):
    while(have_posts()):the_post();
        // 投稿のタイトルを表示
        the_title();
    endwhile;
else :
    // 投稿が見つからない場合の表示
    echo '投稿がありません';
endif;
?>

上記コードはWordPressのループを使用して、投稿のタイトルを一覧で表示しています。

have_posts()関数は、投稿やページなどのコンテンツが存在するかどうかを確認します。

まだ表示されていない投稿がある場合にtrueを返します。

「while(have_posts()):the_post();」の部分に関しては、メインループの開始をしています。

whileを使って、まだ表示されていない各投稿を順番に取得し、the_post() 関数で次の投稿をロードします。

the_title()関数に関しては記事のタイトルを表示するテンプレートタグ(関数)です。

もし記事データが0件でデータ取得ができなかった場合は「投稿がありません」というテキストが表示されます。

ちなみに、まとめると以下のPHPテンプレートで上記コードを使えます。

  • index.php
  • category.php
  • archive.php
  • search.php
  • など

記事詳細ページ・固定ページのメインループ

以下のコードは、single.phpやカスタム投稿タイプのPHPテンプレートファイルであるsingle-{カスタム投稿タイプ名}.php、page.php、page-{スラッグ名}.phpなどの詳細ページを表示するPHPテンプレートファイルに記述するコードの雛形になります。

<?php get_header(); ?>

<div>
    <main>
        <?php
        // メインループの開始
        if(have_posts()):
            while(have_posts()):the_post();
                // 投稿のタイトルを表示
                the_title();
                // 投稿の本文を表示
                the_content();
            endwhile;
        else:
            // 投稿が見つからない場合の表示
            echo '投稿がありません';
        endif;
        ?>
    </main>
</div>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

上記コードの内容は「記事一覧系のメインループ」のコードの内容とほぼ同じです。

違いは詳細ページとして必要な記事本文を表示するためのthe_content()関数が必要なぐらいかと思います。

これで詳細ページの内容を表示することができます。

ちなみに、まとめると以下のPHPテンプレートで上記コードを使えます。

  • single.php
  • single-{カスタム投稿タイプ名}.php
  • page.php
  • page-{スラッグ名}.php
  • など

メインループが成り立つWordPress本体の処理とは

メインループについてわかりましたら、そもそもなぜこのメインループが成り立つのかを確認しておきましょう。

メインループが成立するためにWordPressでは以下の処理を上から順番に裏側でおこなっています。

  • URLの解析とクエリの生成
  • クエリの実行
  • ループの実行
  • テンプレートのロード
  • テンプレートの表示

それぞれ解説していきます。

URLの解析とクエリの生成

ユーザーがアクセスしたURLを解析し、どのページや投稿が表示されるべきかを特定します。このとき、クエリパラメーターが解析され、表示内容を決定するためのクエリが生成されます。

クエリの実行

生成されたクエリがデータベースに送信され、WordPressのテーブルから必要な情報(投稿やページの内容など)が取得されます。このとき、条件や並び替えなどの指定がクエリに含まれます。

WordPressループの実行(当記事のメインの内容)

取得したデータがループに渡され、1つずつ処理されます。これは、have_posts()関数とthe_post()関数を使って行われます。WordPressはループの中で、投稿やページの情報を取得し、テーマのループ内テンプレートを使用して表示します。

テンプレートのロード

ループ内で表示される各投稿やページの情報を、テーマのテンプレートファイルに渡します。これにより、投稿のタイトルや本文、カスタムフィールドなどが適切なHTML構造とともに表示されます。

テンプレートの表示

最後に、生成されたHTMLコードがブラウザに送信され、ユーザーが閲覧できるページとして表示されます。ブラウザはHTMLコードを解釈し、それに基づいて表示を構築します。

これらのステップが連続して実行されることで、WordPressのメインループが成り立ち、ユーザーがブラウザでコンテンツを閲覧することが可能になります。

ちなみに初心者エンジニアの方はこの内容が理解できなくてもテーマ開発は問題なくできるかと思いますので、今はいったん気にしないでスルーしていただいて大丈夫です。

サブループとは

サブループとは、まず簡単にご説明すると、メインループとは別に記事一覧などを複数表示させたい場合、また記事一覧を固定ページ(page.php、page-{スラッグ名}.phpなど)に表示したい場合に必要なループ処理のことをいいます。

別のいい方をすると、メインループとは別で独自のクエリを定義してそのクエリをWP_Queryで実行するループのことをいいます。

WordPressのループにおける「クエリ」とは、データベースから情報を取得するための問い合わせ(クエリ)のことを指します。

WordPressでは、投稿やページなどのコンテンツを取得するためにクエリが使用されます。

これにより、特定の条件を満たす投稿やページのみを取得したり、表示順序を指定したりすることが可能になります。

例えば、下図をご確認ください。

上図のページでは、category.phpのテンプレートで構成されたカテゴリー別記事一覧ページになりますが、通常メインループは一つのテンプレートファイルに対して一度しか使えません。

そのため、普通に考えたら記事一覧はカテゴリー機能によってカテゴライズされた記事一覧のみしか表示できないところを、サブループを使うことによって上図のようにサイドバーなどに別の記事一覧を表示することが可能となります。

メインループは一度のページ表示で使えるのは一回のみですが、サブループは何回でも使用することができるので、例えばさらに新着記事一覧などを追加で表示することが可能です。

サブループの注意点としては、何回も記事一覧を呼び出せるとはいえ、使いすぎるとデータベースの読み込みがたくさん発生することによって処理が重くなり、それに合わせて動作がかなり重くなってしまうので使い過ぎには注意が必要です。

サブループは、具体的には以下のようなコードになります。

<?php
// クエリのパラメーターを設定
$args = array(
    'post_type'      => 'post', // 投稿タイプ
    'posts_per_page' => 10,     // 表示件数
);
// WP_Queryを使用してクエリを実行
$my_query = new WP_Query( $args );
// ループで取得した投稿を表示
if ($my_query->have_posts()):
    while ($my_query->have_posts()):$my_query->the_post();
        // 投稿の表示
        the_title();
    endwhile;
    wp_reset_postdata(); // ループの後に必要
else :
    echo '投稿がありません';
endif;

上記コードでは、WP_Query クラスを使用して、指定された条件に基づいて投稿を取得しています。

$args配列には、取得する投稿の条件が指定されており、例えば post_type で投稿タイプ、 posts_per_page で表示件数が指定されています。

その後、WP_Query オブジェクトを使用してクエリを実行し、have_posts()関数とthe_post()関数を使ってループ内で取得した投稿を表示しています。

ループ後には wp_reset_postdata()関数を呼び出して、元のクエリをリセットする必要があります。

このサブループを使用することで、特定の投稿に関連するカスタムフィールド、コメント、関連記事などの情報を表示することができます。これにより、ページや投稿のコンテンツをより多彩に表示することが可能になります。

メインループとサブループの違い

ひととおり理解できたところで、メインループとサブループの違いについても解説していきたいと思います。

役割の違い

  • メインループの場合
    WordPressのページや投稿の主要なコンテンツを表示するためのループです。通常、テーマのインデックスページやシングルページなどで使用されます。
  • サブループの場合
    メインループ内で使用され、追加の情報を表示するためのループです。メインループの各投稿やページに関連する情報を取得し、表示するために使用されます。

コードの配置の違い

  • メインループの場合
    ページや投稿の主要なコンテンツを表示するために、通常、テーマのインデックスファイル(index.php)やシングルページファイル(single.php)などの主要なテンプレートファイル内で実行されます。
  • サブループの場合
    特定の投稿やページに関連する情報(記事一覧)を取得し表示するために使用されます。

簡単にまとめると、メインループはページや投稿の主要なコンテンツを表示し、サブループはメインループでは再現できない人気ランキング記事一覧や新着記事一覧などの追加情報を表示するために使用されます。

仕事でよくある実装例

ここでは仕事でよくある実装例をこれまでの筆者の経験からご紹介したいと思います。

新着記事一覧

新着記事一覧については以下のコードを使用します。

以下のコードをsidebar.phpなどにPHPテンプレートにコピー&ペーストしてください。

<?php
// 新着記事を取得するクエリ
$args = array(
    'post_type' => 'post', // 投稿タイプを指定
    'posts_per_page' => 5, // 表示する投稿の数
    'orderby' => 'date', // 日付順に並べ替える
    'order' => 'DESC', // 降順(新しい順)に並べ替える
);
$new_posts_query = new WP_Query($args);
// 新着記事がある場合の表示
if ($new_posts_query->have_posts()) {
    echo '<h2>新着記事一覧</h2><ul>';
    while ($new_posts_query->have_posts()) {
        $new_posts_query->the_post();
        echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
    }
    echo '</ul>';
}
// ループのリセット
wp_reset_postdata();
?>

上記コードのペーストが完了したら、ご自身のサイトに適した形でカスタマイズしてください。

関連記事一覧

関連記事一覧については以下のコードを使用します。

以下のコードをsingle.phpなどの記事詳細ページのPHPテンプレートにコピー&ペーストしてください。

<div class="single__detail__box__left__box__related">
    <div class="single__detail__box__left__box__related__box">
        <h2 class="single__detail__box__left__box__related__box__title">
        関連する記事
        </h2>
    </div>
    <ul class="single__detail__box__left__box__related__box__list">
        <?php
        $taxonomy = 'category';
        $current_terms = get_the_terms($post->ID, $taxonomy);
        $terms = array();
        if($current_terms):
            foreach($current_terms as $current_term):
                array_push($terms, $current_term->slug);
            endforeach;
        endif;
        $args = array(
            'post_type' => 'post',
            'posts_per_page' => 6,
            'orderby' => 'rand',
            'post__not_in' => array($post->ID),
            'tax_query' => array(
                array(
                'taxonomy' => $taxonomy,
                'terms' => $terms,
                'field' => 'slug',
                ),
            ),
        );
        $my_query = new WP_Query($args);
        if($my_query->have_posts()):
            while($my_query->have_posts()):$my_query->the_post();
            ?>
            <li class="single__detail__box__left__box__related__box__list__items">
                <a class="single__detail__box__left__box__related__box__list__items__link" href="<?php echo get_permalink(); ?>">
                    <span class="single__detail__box__left__box__related__box__list__items__thumbnail">
                    <?php
                    if(has_post_thumbnail()):
                        the_post_thumbnail();
                    else:
                    ?>
                    <img class="single__detail__box__left__box__related__box__list__items__thumbnail__img" src="<?php echo get_theme_file_uri(); ?>/image/noimage.png">
                    <?php
                    endif;
                    ?>
                    </span>
                    <span class="single__detail__box__left__box__related__box__list__items__meta">
                        <h3 class="single__detail__box__left__box__related__box__list__items__meta__title">
                            <?php echo get_the_title(); ?>
                        </h3>
                        <span class="single__detail__box__left__box__related__box__list__items__meta__catAndTime">
                            <span class="single__detail__box__left__box__related__box__list__items__meta__cat">
                            <?php
                            $related_cats = get_the_terms($post->ID, $taxonomy);
                            if(!empty($related_cats)):
                                foreach($related_cats as $val):
                            ?>
                            <span class="single__detail__box__left__box__related__box__list__items__meta__cat__link">
                                <?php echo $val->name; ?>
                            </span>
                            <?php
                                endforeach;
                            endif;
                            ?>
                            </span>
                            <span class="single__detail__box__left__box__related__box__list__items__meta__time">
                                <?php echo get_the_time('Y.m.d'); ?>
                            </span>
                        </span>
                    </span>
                </a>
            </li>
            <?php
            endwhile;
        else:
        ?>
        <p>現在準備中です。</p>
        <?php
        endif;
        wp_reset_postdata();
        ?>
    </ul>
</div>

上記コードは記事詳細ページに下あたりに3列3行で同じカテゴリーの記事一覧を表示させるコードになります。

また、上記PHPコードに対応するCSSコードも合わせて掲載しておきます。

以下のコードをCSSファイルなどにコピー&ペーストしてください。

.single__detail__box__left__box__related {
    margin-top: 30px;
}
.single__detail__box__left__box__related__box {
    margin-bottom: 20px;
    padding-bottom: 10px;
    border-bottom: 1px solid #555;
}
.single__detail__box__left__box__related__box__title {
    display: flex;
    justify-content: space-between;
    align-items: end;
    font-size: 22px;
}
.single__detail__box__left__box__related__box__title__text {}
.single__detail__box__left__box__related__box__title__count {
    font-size: 11px;
    color: #888;
    font-weight: 400;
}
.single__detail__box__left__box__related__box__list {}
.single__detail__box__left__box__related__box__list:after {
    content: "";
    display: block;
    clear: both;
}
.single__detail__box__left__box__related__box__list__items {
    width: 216px;
    height: 250px;
    float: left;
    margin-right: 26px;
    margin-bottom: 26px;
}
.single__detail__box__left__box__related__box__list__items:nth-child(3n) {
    margin-right: 0;
}
.single__detail__box__left__box__related__box__list__items__link {}
.single__detail__box__left__box__related__box__list__items__thumbnail {
    display: block;
    margin-bottom: 12px;
}
.single__detail__box__left__box__related__box__list__items__thumbnail__img {
    width: 100%;
    height: 120px;
}
.single__detail__box__left__box__related__box__list__items__meta {
    display: block;
}
.single__detail__box__left__box__related__box__list__items__meta__title {
    font-size: 15px;
    margin-bottom: 9px;
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.single__detail__box__left__box__related__box__list__items__meta__catAndTime {
    display: flex;
    align-items: center;
    font-size: 13px;
}
.single__detail__box__left__box__related__box__list__items__meta__cat {}
.single__detail__box__left__box__related__box__list__items__meta__cat__link {
    display: inline-block;
    /* background: #333; */
    background: #2a627e;
    color: #fff;
    padding: 3px 7px;
    font-size: 11px;
    border-radius: 2px;
}
.single__detail__box__left__box__related__box__list__items__meta__time {
    display: inline-block;
    margin-left: 9px;
    color: #777;
}

上記コードのペーストが完了したら、ご自身のサイトに適した形でカスタマイズしてください。

こちらに関連する記事を合わせて載せておきますので、もっと詳しく知りたい方は以下の記事をご確認ください。

まとめ

WordPressループであるメインループからサブループについての解説は以上になります。

ループという仕組みはWordPress構築において必ず必要になる技術なので、エンジニアはマストでこのループを扱えなければエンジニアとしての仕事をこなすことができません。

当記事ではこのメインループやサブループについて解説し、また仕事での実装例としてサンプルコードを掲載いたしました。

お仕事で使えることを意識して当記事を執筆いたしましたので、よろしければぜひお役立ていただけましたら幸いです。

執筆者

ワードプレスマガジン編集部 高澤 翔汰

歴4年目(2024年8月以降から5年目です)のエンジニアです!
CMSでのサイト構築とWebデザイン制作を兼任して4年目になります。
自作のiOSアプリ(iPhoneアプリ)やWordPressプラグインを開発することもあり、まだまだ現在進行形で勉強中です!