2026年5月20日

2026年5月20日

カスタム投稿タイプのアーカイブページを作る方法|has_archive・archive-{post_type}.php・表示件数

カスタム投稿タイプ(例: news)の記事を /news/ のような一覧ページで見せるには、投稿タイプの登録時に has_archive を有効にし、必要に応じて専用のテンプレートを用意します。この記事では、クラシックテーマ(PHP テンプレート)を前提に、登録からテンプレート、表示件数の調整、404 の対処までを順に説明します。

関数と引数は developer.wordpress.org のリファレンス(register_post_type()、テンプレート階層、pre_get_posts)で2026年10月時点の内容を確認しています。

アーカイブページが表示される仕組み

  • register_post_type() の has_archive が true のとき、WordPress は一覧用の URL とリライトルールを作ります。既定値は false で、このままでは一覧ページはありません。
  • has_archive に文字列を渡すと、それが一覧の URL になります(例: 'has_archive' => 'topics' なら /topics/)。true のときは rewrite の slug(未指定なら投稿タイプ名)が使われます。
  • 一覧ページを開くと、テーマの中から次の順でテンプレートが探されます。
優先順 クラシックテーマ ブロックテーマ
1 archive-news.php templates/archive-news.html
2 archive.php templates/archive.html
3 index.php templates/index.html

テンプレート階層の全体は WordPressのテンプレート階層 も参考にしてください。

手順1: has_archive を有効にして投稿タイプを登録する

テーマの functions.php(またはサイト用の独自プラグイン)に書きます。

<?php
function mytheme_register_news_post_type() {
    register_post_type( 'news', array(
        'labels'       => array(
            'name'          => 'ニュース',
            'singular_name' => 'ニュース',
            'add_new_item'  => 'ニュースを追加',
            'edit_item'     => 'ニュースを編集',
            'all_items'     => 'ニュース一覧',
            'archives'      => 'ニュース一覧',
        ),
        'description'  => '当社からのお知らせを掲載しています。', // 一覧ページの説明文に使える
        'public'       => true,
        'has_archive'  => true,              // /news/ に一覧ページを作る
        'rewrite'      => array(
            'slug'       => 'news',
            'with_front' => false,           // パーマリンクの前置部分(/blog/ など)を付けない
        ),
        'supports'     => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
        'show_in_rest' => true,              // ブロックエディターで編集する
        'menu_icon'    => 'dashicons-megaphone',
    ) );
}
add_action( 'init', 'mytheme_register_news_post_type' );

パーマリンクを更新する

has_archive や rewrite を追加・変更したあとは、リライトルールを作り直すまで一覧の URL が 404 になります。管理画面の「設定」→「パーマリンク」を開くとルールが作り直されます(「変更を保存」を押しても同じです)。WP-CLI が使える環境では次のコマンドでも構いません。

wp rewrite flush

flush_rewrite_rules() を init で毎回呼ぶのは処理が重くなるので避けます。プラグインで登録する場合は、有効化フック(register_activation_hook())の中で一度だけ呼ぶのが公式ドキュメントの推奨です。

一覧ページの URL は、テンプレートやメニューで次のように取得できます。

<?php
echo esc_url( get_post_type_archive_link( 'news' ) ); // https://example.com/news/

手順2: archive-news.php を作る

archive-news.php をテーマのフォルダー直下に置くと、ニュースの一覧だけがこのテンプレートで表示されます。子テーマを使っている場合は子テーマに置きます。

<?php
get_header();
?>
<main id="main" class="site-main">
    <header class="page-header">
        <h1 class="page-title"><?php post_type_archive_title(); ?></h1>
        <?php the_archive_description( '<div class="archive-description">', '</div>' ); ?>
    </header>

    <?php if ( have_posts() ) : ?>
        <div class="news-list">
            <?php while ( have_posts() ) : the_post(); ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                    <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                    <time datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>"><?php echo esc_html( get_the_date() ); ?></time>
                    <?php the_excerpt(); ?>
                </article>
            <?php endwhile; ?>
        </div>

        <?php
        the_posts_pagination( array(
            'prev_text' => '前のページ',
            'next_text' => '次のページ',
        ) );
        ?>
    <?php else : ?>
        <p>ニュースはまだありません。</p>
    <?php endif; ?>
</main>
<?php
get_footer();
  • post_type_archive_title() は投稿タイプの名前(labels の name)を出力します。
  • the_archive_description() は、投稿タイプの一覧では register_post_type() の description を出力します。説明が空なら何も出ません。
  • 記事一覧の部分をテーマ内の部品に分けたい場合は get_template_part( 'template-parts/content', 'news' ) のように呼び、template-parts/content-news.php を作ります。ファイルが無いと何も表示されないので注意してください。

ブロックテーマでは PHP テンプレートの代わりに、サイトエディターで「ニュース」の一覧用テンプレートを追加するか、テーマの templates/archive-news.html に「クエリーループ」ブロックを置きます。

手順3: 表示件数と並び順を pre_get_posts で変える

一覧ページの表示件数は、既定では「設定」→「表示設定」の「1ページに表示する最大投稿数」に従います。ニュースだけ変えたい場合は、テンプレートの中で WP_Query を作り直すのではなく、pre_get_posts でメインクエリを書き換えます。こうするとページ送りもそのまま動きます。

<?php
function mytheme_news_archive_query( $query ) {
    // 管理画面やサブクエリには手を出さない
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    if ( $query->is_post_type_archive( 'news' ) ) {
        $query->set( 'posts_per_page', 12 );
        $query->set( 'orderby', 'date' );
        $query->set( 'order', 'DESC' );
    }
}
add_action( 'pre_get_posts', 'mytheme_news_archive_query' );

テンプレートの中で new WP_Query() や query_posts() を使って件数を変えると、メインクエリの件数とずれて2ページ目以降が 404 になることがあります。pre_get_posts の使い方は pre_get_postsでメインクエリを変更する方法 で詳しく説明しています。

手順4: 見出しの「アーカイブ:」を消す

archive.php で the_archive_title() を使っていると、投稿タイプの一覧は「アーカイブ: ニュース」のように前置きが付きます。WordPress 5.5 以降は、前置きだけを get_the_archive_title_prefix フィルターで外せます。

<?php
function mytheme_archive_title_prefix( $prefix ) {
    if ( is_post_type_archive( 'news' ) ) {
        return '';
    }
    return $prefix;
}
add_filter( 'get_the_archive_title_prefix', 'mytheme_archive_title_prefix' );

archive-news.php で post_type_archive_title() を使っている場合は、前置きは最初から付きません。

複数の投稿タイプを archive.php でまとめて扱う

投稿タイプごとにテンプレートを分けず、archive.php 1つで見出しや部品を切り替えることもできます。

<?php
get_header();
?>
<main id="main" class="site-main">
    <h1 class="page-title"><?php the_archive_title(); ?></h1>

    <?php if ( have_posts() ) : ?>
        <?php while ( have_posts() ) : the_post(); ?>
            <?php get_template_part( 'template-parts/content', get_post_type() ); ?>
        <?php endwhile; ?>
        <?php the_posts_pagination(); ?>
    <?php else : ?>
        <p>記事が見つかりませんでした。</p>
    <?php endif; ?>
</main>
<?php
get_footer();

get_template_part( 'template-parts/content', get_post_type() ) は、content-news.php があればそれを、無ければ content.php を読み込みます。

一覧ページが 404 になるときの確認点

症状 確認すること
/news/ が 404 has_archive が true か。登録後に「設定」→「パーマリンク」を開いたか
/news/ に固定ページが表示される 同じスラッグ news の固定ページがあると衝突します。どちらかのスラッグを変えます
2ページ目以降だけ 404 テンプレート内で独自の WP_Query を使っていないか。件数は pre_get_posts で変えます
一覧は出るが別のテンプレートが使われる ファイル名が archive-{投稿タイプ名}.php になっているか(rewrite のスラッグではなく、登録した投稿タイプ名)
何も表示されない public や publicly_queryable が false になっていないか

カスタム投稿タイプの記事ページ自体が 404 になる場合は カスタム投稿タイプが404になるときの対処 も確認してください。

まとめ

  • register_post_type() で has_archive を true(または一覧用のスラッグ)にし、「設定」→「パーマリンク」を開いてルールを作り直す
  • 専用の見た目にするなら archive-{投稿タイプ名}.php(ブロックテーマは templates/archive-{投稿タイプ名}.html)を作る
  • 表示件数や並び順は pre_get_posts でメインクエリを変える
  • 見出しの「アーカイブ:」は get_the_archive_title_prefix で外せる

お気軽にご相談ください

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