2026年5月26日

2026年5月26日

WordPressの条件分岐タグ(is_single等)の正しい使い方まとめ

WordPressの条件分岐タグ(Conditional Tags)は、is_single() や is_page() のように「いま表示しているのはどんなページか」を true / false で教えてくれる関数です。正しく使うためのポイントは、似た関数の違いを押さえること、メインクエリが決まった後に呼ぶこと、そして pre_get_posts の中ではクエリオブジェクトのメソッドを使うことの3つです。この記事では、よく使う条件分岐タグの違いと、思ったとおりに動かないときの原因を整理します。

条件分岐タグは「メインクエリ」を見ている

条件分岐タグの多くは、URL から WordPress が組み立てたメインクエリ(グローバルの $wp_query)の状態を返しています。たとえば is_single() は「メインクエリが投稿の個別ページを表しているか」を答える関数で、「ループ中のこの投稿が投稿タイプ post か」を答える関数ではありません。

この前提を押さえておくと、つまずきの多くが説明できます。

  • メインクエリが決まる前に呼ぶと、正しい答えが返らない
  • サイドバーなどのサブループの中で呼んでも、答えはメインクエリについてのもの
  • 投稿ごとの判定には、get_post_type() や has_term() など投稿を指定する関数を使う

よく使う条件分岐タグと違い

個別ページ系:is_single / is_page / is_singular

  • **is_single()**:投稿の個別ページ。カスタム投稿タイプの個別ページも含み、固定ページでは false
  • **is_page()**:固定ページ。is_page( 'contact' ) のように ID・スラッグ・タイトル・配列で絞り込める
  • **is_singular()**:投稿・固定ページ・添付ファイル・カスタム投稿タイプを含む「1件表示」のページすべて。is_singular( 'product' ) のように投稿タイプで絞り込める

「通常の投稿の記事ページだけ」に限定したいときは is_singular( 'post' ) が意図を読み取りやすい書き方です。is_single() だけだとカスタム投稿タイプのページも true になるため、プラグインで投稿タイプを追加したときに表示が崩れる原因になります。添付ファイルページを除外したい場合は、is_attachment() を組み合わせて明示しておくと安全です。

トップページ系:is_front_page と is_home

この2つは名前が紛らわしく、混乱しやすい組み合わせです。

  • **is_front_page()**:サイトのフロントページ(トップページ)
  • **is_home()**:ブログの投稿一覧ページ

「設定」→「表示設定」でホームページの表示を「最新の投稿」にしている場合は、トップページで両方が true になります。「固定ページ」を選んでいる場合は、トップに指定した固定ページで is_front_page() が true、投稿ページに指定したページで is_home() が true になり、両者は別のページを指します。トップページだけに何かを出したいなら、基本は is_front_page() を使います。

アーカイブ系

  • **is_archive()**:カテゴリー・タグ・タクソノミー・投稿タイプ・作成者・日付などのアーカイブ全般
  • **is_category() / is_tag()**:カテゴリー、タグのアーカイブ。スラッグや ID で絞り込める
  • **is_tax()**:カスタムタクソノミーのアーカイブ。is_tax( 'genre', 'novel' ) のように指定できる。引数なしの場合、カテゴリーとタグのアーカイブでは false
  • **is_post_type_archive()**:カスタム投稿タイプの一覧ページ
  • **is_search() / is_404()**:検索結果ページ、404ページ
  • **is_paged()**:2ページ目以降

サイトの状態や利用者に関するもの

  • **is_admin()**:管理画面を表示しているか。「管理者かどうか」ではない。Ajax の admin-ajax.php 経由のリクエストでも true になる
  • **current_user_can()**:利用者が特定の権限を持っているか。権限の判定はこちらを使う
  • **is_user_logged_in()**:ログインしているか
  • **wp_doing_ajax()**:Ajax リクエスト中か
  • **is_page_template( 'templates/full-width.php' )**:指定したページテンプレートが使われているか

呼び出すタイミング

条件分岐タグは、メインクエリが実行された後でないと正しく動きません。functions.php の最上位や、plugins_loaded、init のフックの中で呼ぶと、開発時に「クエリの実行前に条件分岐タグは動作しない」という趣旨の通知(_doing_it_wrong)が出て、false が返ります。

使えるタイミングの代表は次のとおりです。

  • wp アクション以降(template_redirect、wp_enqueue_scripts、wp_head など)
  • テーマのテンプレートファイルの中

よく使うのは、必要なページだけでスクリプトを読み込む書き方です。

<?php
// 子テーマの functions.php
add_action( 'wp_enqueue_scripts', function () {
    // お問い合わせページだけでフォーム用のスクリプトを読み込む
    if ( is_page( 'contact' ) ) {
        wp_enqueue_script(
            'mytheme-contact',
            get_stylesheet_directory_uri() . '/js/contact.js',
            array(),
            '1.0.0',
            true
        );
    }

    // 通常の投稿の個別ページだけで目次用のスタイルを読み込む
    if ( is_singular( 'post' ) ) {
        wp_enqueue_style( 'mytheme-toc', get_stylesheet_directory_uri() . '/css/toc.css', array(), '1.0.0' );
    }
} );

ページ単位でリダイレクトや出力を変える処理は、template_redirect アクションに書くのが一般的です。

pre_get_posts ではメソッドを使う

一覧ページの表示件数などを変えるときに使う pre_get_posts は、クエリが実行される直前に呼ばれます。ここではグローバル関数の is_home() ではなく、引数で受け取ったクエリオブジェクトのメソッドを使います。

<?php
add_action( 'pre_get_posts', function ( $query ) {
    // 管理画面と、メインクエリ以外は対象外にする
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    // ブログの投稿一覧だけ表示件数を変える
    if ( $query->is_home() ) {
        $query->set( 'posts_per_page', 6 );
    }

    // ジャンルのアーカイブだけ並び順を変える
    if ( $query->is_tax( 'genre' ) ) {
        $query->set( 'orderby', 'title' );
        $query->set( 'order', 'ASC' );
    }
} );

$query->is_main_query() の確認を省くと、ウィジェットや関連記事の WP_Query にも同じ変更がかかり、思わぬ場所の件数や並びが変わります。is_admin() の確認を省くと、管理画面の投稿一覧まで変わってしまいます。

うまく動かないときの確認ポイント

1. いつも false になる

呼び出しが早すぎる可能性が高いです。WP_DEBUG を有効にした開発環境で _doing_it_wrong の通知が出ていないか確認し、処理を wp 以降のフックに移します。スラッグで指定している場合は、つづりや、日本語スラッグのエンコードの違いも確認します。ID で指定すると、スラッグ変更の影響を受けません。

2. 関係ないページでも true になる

is_single() がカスタム投稿タイプでも true になっている、is_archive() がすべてのアーカイブに当てはまっている、といった「範囲の広い関数」を使っているケースです。is_singular( 'post' ) や is_category( 'news' ) のように範囲を絞ります。

3. ループの中で投稿ごとに判定できない

条件分岐タグはメインクエリの状態を返すため、サブループの投稿ごとには変わりません。ループの中では get_post_type()、has_term( 'news', 'category' )、has_post_thumbnail() など、現在の投稿を対象にする関数を使います。

4. スマートフォンだけ表示を変えたつもりが崩れる

wp_is_mobile() は利用者のブラウザー情報(ユーザーエージェント)で判定するため、ページキャッシュを使っていると、最初にアクセスした端末向けの HTML がほかの端末にも配られることがあります。見た目の切り替えは CSS のメディアクエリで行うほうが安全です。

条件分岐を増やしすぎない工夫

header.php の中に if ( is_front_page() ) … elseif ( is_page( 'about' ) ) … と分岐を重ねていくと、後から読む人が追えなくなります。ページの種類ごとに見た目を大きく変えたいなら、テンプレート階層を使って front-page.php や single-product.php のようにファイルを分けるほうが整理しやすくなります。

見た目だけの違いであれば、WordPress が body_class() で出力するクラス(home、single-post、page-id-12 など)を CSS で使う方法もあります。ブロックテーマの場合は、テンプレートやテンプレートパーツをサイトエディターで分ける方法が基本になり、PHP の条件分岐は必要な場面に限って使います。

編集は親テーマを直接触らず、子テーマか自作プラグインで行い、ステージング環境で表示を確認してから本番に反映してください。関数の引数や挙動には追加や変更が入ることがあるため(2026年10月現在)、利用中のバージョンの開発者向けリファレンスも併せて確認しておくと安心です。

まとめ

  • 条件分岐タグは「メインクエリが表すページ」を判定する関数で、ループ中の投稿ごとの判定ではない
  • 通常の投稿だけなら is_singular( 'post' )、トップページなら is_front_page()、投稿一覧なら is_home()
  • is_admin() は管理画面かどうか。権限の判定は current_user_can() を使う
  • 呼ぶのは wp アクション以降やテンプレートの中。pre_get_posts では $query->is_main_query() などのメソッドを使う
  • 分岐が増えたら、テンプレート階層や body_class() で整理する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲