カスタム投稿タイプの一覧ページだけを作成する方法【詳細ページを作成しない】

※本ブログの目的は個人の備忘録であり、コードは参考用として掲載しています。
実際に使用される際は、ご自身の環境で十分に動作確認を行ってください。
コードの利用によって生じたいかなる問題についても責任を負いかねますので、あらかじめご了承ください。

はじめに

WordPressでカスタム投稿タイプを使って投稿一覧ページ(アーカイブ)を作成することはよくありますが、場合によっては「詳細ページは不要で、アーカイブ一覧ページのみ表示したい」という要件があります。

例えば以下のようなパターンが考えられます。

  • 実績や製品一覧だけを一覧表示したい
  • お知らせやメディア掲載情報をループで見せたいが、詳細ページを用意したくない
  • SEO的に中身の薄い詳細ページをインデックスさせたくない

このような場合に「カスタム投稿タイプの一覧ページ(アーカイブページ)だけ作成し、詳細ページ(シングルページ)を作成しない方法」を以下で紹介します。

function.phpで作成する場合(register_post_type()

register_post_type()を使ってカスタム投稿タイプを functions.php に以下のように登録します。

add_action('init', function () {
  register_post_type('news', [
    'label' => '新着情報',
    'public' => false,
    'publicly_queryable' => true,
    'exclude_from_search' => false,
    'has_archive' => true,
    'rewrite' => ['slug' => 'news'], // URLスラッグを変更したい場合
    'show_ui' => true,
    'supports' => ['title'], // 本文エディターなどが不要な場合(タイトルのみを入力させたい場合)
  ]);
});

なぜこの方法で「詳細ページが作成されない」のか?

WordPress では public => false を指定すると、WordPressは内部的に以下を自動で設定します。

  • exclude_from_search => true
  • publicly_queryable => false
  • show_ui => false
  • show_in_nav_menus => false

この状態では投稿の詳細ページが生成されず、URLにアクセスしても 404 Not Found になります。

publicはデフォルトがfalseなので、デフォルトのままでは「管理画面にも表示されず、URLからもアクセスできない隠し投稿タイプ」になります。正直あまりそのまま使うことはないと思います。
public は「管理画面やフロントの公開の総合的なスイッチ」と捉えられるでしょう。

この動作は、公式ドキュメントの register_post_type() の解説 にも次のように明記されています。

If no value is specified for exclude_from_search, publicly_queryable, show_in_nav_menus, or show_ui, they inherit their values from public.

register_post_type() – Function | Developer.WordPress.org

Google翻訳を利用すると、「exclude_from_search、publicly_queryable、show_in_nav_menus、または show_uiに値が指定されていない場合は、publicから値が継承されます。」ということです。

ただし、publicly_queryable => true を別途指定することで、アーカイブ一覧の取得や表示は許可されます。

publicly_queryable

(boolean) (optional) Whether queries can be performed on the front end as part of parse_request().

register_post_type() – Function | Developer.WordPress.org

publicly_queryable (boolean) (オプション) parse_request() の一部としてフロントエンドでクエリを実行できるかどうか。」(Google翻訳)

WordPressでいう「クエリ」とは、簡単に言うと、どの投稿やページを表示するかを決定するための検索条件を指します。

たとえば、トップページに「新着情報の投稿を3件だけ表示したい」といった場合、以下のようにWP_Queryクラスを使って条件を指定し、データベースから該当投稿を取得します。

$args = array(
    'post_type' => 'news',            // カスタム投稿タイプ「news」
    'posts_per_page' => 3,            // 3件だけ取得
    'orderby' => 'date',              // 日付順
    'order' => 'DESC',                // 新しい順
);
$the_query = new WP_Query($args);

このような「検索条件を指定して投稿を取得する処理」がWordPress内部では「クエリ」と呼ばれています。

一方、WordPressのURLにアクセスした際、たとえばカスタム投稿タイプの一覧ページ(アーカイブページ)や投稿詳細ページ(シングルページ)など、これらのURLに対応する表示内容も、内部的にはWP_Queryによるクエリ処理で決定されます。

ここで重要なのが publicly_queryable の設定です。

publicly_queryabletrue の場合、フロントエンドからURLに基づいたクエリが許可されます。 つまり、該当投稿タイプのアーカイブ一覧や詳細ページの表示をWordPressが内部処理で認めます。
逆に false の場合は、URLアクセスでのクエリは拒否され、アクセスすると 404 エラーになります。

ただし、public => falseを設定しているため、許可しているだけで表示するわけではありません。public => false にすると、WordPressはその投稿タイプを「非公開扱い」にします。

publicfalse であるため、「単一投稿ページ(詳細ページ)は通常は表示されない」などの制限が残り、publicly_queryabletrueにして一覧ページへのアクセスは許可しているが、publicfalseのため詳細ページは表示されないというわけです。

※他の設定も忘れないように!

上記でも説明したように、public => falsepublicly_queryable以外にもexclude_from_searchshow_in_nav_menusshow_uiの設定にも継承されます。

また、重要なのがhas_archiveです。これをtrueにすることで一覧ページが表示されるようになります。

以下の点に気をつけましょう。

  • show_uitrueにしなければ管理画面に表示されない
  • exclude_from_searchfalseにしなければフロントエンドの検索結果に含まれない
  • has_archivetrueにしなければ一覧ページが表示されない

プラグインCPT UIで作成する場合

CPT UIでは項目が個別にすべて用意されており、設定はregister_post_type()より簡単かもしれません。

また、CPT UIに関してはpublicである「公開」設定のデフォルト値がtrueなので、今回のようなときはfalseに設定しましょう。

他に関してはhas_archiveである「アーカイブ」設定をtrueにすれば他はデフォルト値で問題ないです。

まとめ

各種設定に必要な値を表にまとめました。

register_post_type()

CPT UI

public

公開

false

publicly_queryable

一般公開クエリー可

true

show_ui

UI を表示

true

has_archive

アーカイブあり

true

exclude_from_search

検索から除外

false

さいごに

いかがだったでしょうか。

このように、register_post_type() の設定だけで「一覧ページだけを表示し、詳細ページを無効化する」ことは簡単に実現できます。

Wordpressは実現したいことが有志のおかげでネットの海に有益なコードや情報がたくさんあります。

コピペで簡単にやりたいことが実現できることも魅力ですが、日常的に利用している関数のパラメーターについても、よく調べて理解することが大切ですね。

参考

register_post_type() – Function | Developer.WordPress.org