2026年6月24日

2026年6月24日

WordPressカスタム投稿タイプのアーカイブページを設定する方法

はじめに

WordPressでカスタム投稿タイプを作成したものの、アーカイブページが404エラーになったり、正しく表示されないことがあります。この記事では、カスタム投稿タイプのアーカイブページを正しく設定する方法を5つのステップで解説します。

症状・原因

  • カスタム投稿タイプのアーカイブURL(例:/news/)にアクセスすると404エラーが発生する
  • has_archive を設定していないため、WordPressがアーカイブURLを認識しない
  • パーマリンクのフラッシュ(再構築)が行われておらず、リライトルールが古いままになっている
  • archive-{post_type}.php テンプレートファイルが存在せず、デフォルトの archive.php も適切でない

解決手順

ステップ1:register_post_type で has_archive を有効化する

register_post_type() の引数に has_archiverewrite を正しく設定します。has_archivetrue にするか、アーカイブのスラッグを文字列で指定します。

function mytheme_register_news_post_type() {
    $args = [
        'label'         => 'ニュース',
        'labels'        => [
            'name'          => 'ニュース',
            'singular_name' => 'ニュース記事',
            'add_new_item'  => '新規ニュース記事を追加',
            'edit_item'     => 'ニュース記事を編集',
        ],
        'public'        => true,
        'has_archive'   => true,        // アーカイブページを有効化
        'rewrite'       => [
            'slug'       => 'news',     // パーマリンクのスラッグ
            'with_front' => false,      // 前置スラッグなし
        ],
        'supports'      => ['title', 'editor', 'thumbnail', 'excerpt'],
        'menu_icon'     => 'dashicons-megaphone',
        'show_in_rest'  => true,        // Gutenberg対応
    ];
    register_post_type('news', $args);
}
add_action('init', 'mytheme_register_news_post_type');

has_archive => 'news-archive' のように文字列を指定すると、スラッグとは別のアーカイブURLを設定できます。

ステップ2:プラグイン有効化・無効化時にリライトルールをフラッシュする

カスタム投稿タイプを登録した後、パーマリンク設定を保存し直すか、コードでフラッシュする必要があります。プラグインで実装している場合は、有効化・無効化フックを使います。

// プラグイン有効化時にリライトルールを再構築
function mytheme_activate_plugin() {
    // まず投稿タイプを登録してからフラッシュ
    mytheme_register_news_post_type();
    flush_rewrite_rules();
}
register_activation_hook(__FILE__, 'mytheme_activate_plugin');

// プラグイン無効化時にもフラッシュ
function mytheme_deactivate_plugin() {
    unregister_post_type('news');
    flush_rewrite_rules();
}
register_deactivation_hook(__FILE__, 'mytheme_deactivate_plugin');

// テーマのfunctions.phpで使う場合(after_switch_themeフック)
function mytheme_theme_activation() {
    mytheme_register_news_post_type();
    flush_rewrite_rules();
}
add_action('after_switch_theme', 'mytheme_theme_activation');

注意: flush_rewrite_rules() は重い処理なので、init フックの中で毎回呼び出さないようにしてください。

ステップ3:archive-{post_type}.php テンプレートファイルを作成する

WordPressのテンプレート階層に従い、archive-news.php というファイルをテーマディレクトリに作成します。

<?php
// archive-news.php
get_header(); ?>

<main id="main" class="site-main">
    <div class="archive-header">
        <h1 class="archive-title">
            <?php
            // アーカイブタイトルを表示(投稿タイプのラベルが自動的に使われる)
            the_archive_title('<span>', '</span>');
            ?>
        </h1>
        <?php the_archive_description('<div class="archive-description">', '</div>'); ?>
    </div>

    <?php if (have_posts()) : ?>
        <div class="news-grid">
            <?php while (have_posts()) : the_post(); ?>
                <article id="post-<?php the_ID(); ?>" <?php post_class('news-item'); ?>>
                    <?php if (has_post_thumbnail()) : ?>
                        <div class="news-thumbnail">
                            <a href="<?php the_permalink(); ?>">
                                <?php the_post_thumbnail('medium'); ?>
                            </a>
                        </div>
                    <?php endif; ?>
                    <div class="news-content">
                        <h2 class="news-title">
                            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
                        </h2>
                        <time datetime="<?php echo get_the_date('c'); ?>">
                            <?php echo get_the_date(); ?>
                        </time>
                        <?php the_excerpt(); ?>
                    </div>
                </article>
            <?php endwhile; ?>
        </div>
        <?php the_posts_pagination(); ?>
    <?php else : ?>
        <p>記事が見つかりませんでした。</p>
    <?php endif; ?>
</main>

<?php get_footer(); ?>

ステップ4:pre_get_posts フィルターでアーカイブクエリをカスタマイズする

アーカイブページの表示件数や並び順を変更するには、pre_get_posts フィルターを使います。

function mytheme_news_archive_query( $query ) {
    // 管理画面のクエリと、メインクエリ以外はスキップ
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }

    // ニュース投稿タイプのアーカイブページのみ対象
    if ( $query->is_post_type_archive('news') ) {
        // 1ページあたりの表示件数
        $query->set('posts_per_page', 12);

        // 公開日の降順で並び替え
        $query->set('orderby', 'date');
        $query->set('order', 'DESC');

        // 特定のカテゴリー(タクソノミー)でフィルタリング
        // $query->set('tax_query', [
        //     [
        //         'taxonomy' => 'news_category',
        //         'field'    => 'slug',
        //         'terms'    => 'press-release',
        //     ],
        // ]);
    }

    // タクソノミーアーカイブにも投稿タイプを含める場合
    if ( $query->is_tax('news_category') ) {
        $query->set('post_type', ['news']);
        $query->set('posts_per_page', 10);
    }
}
add_action('pre_get_posts', 'mytheme_news_archive_query');

ステップ5:ナビゲーションメニューとパンくずリストに追加する

カスタム投稿タイプのアーカイブページへのリンクをメニューやパンくずリストに追加します。

// ナビゲーションメニューにカスタム投稿タイプのアーカイブリンクを動的追加
function mytheme_add_news_to_menu( $items, $args ) {
    if ( $args->theme_location === 'primary' ) {
        $news_archive_url = get_post_type_archive_link('news');
        $is_active = is_post_type_archive('news') || get_post_type() === 'news';
        $active_class = $is_active ? ' current-menu-item' : '';

        $items .= sprintf(
            '<li class="menu-item%s"><a href="%s">ニュース</a></li>',
            $active_class,
            esc_url($news_archive_url)
        );
    }
    return $items;
}
add_filter('wp_nav_menu_items', 'mytheme_add_news_to_menu', 10, 2);

// パンくずリストに対応(Yoast SEOを使用する場合)
function mytheme_news_breadcrumb_links( $links ) {
    if ( is_singular('news') || is_post_type_archive('news') ) {
        $archive_url = get_post_type_archive_link('news');
        // アーカイブリンクをパンくずに挿入
        array_splice($links, 1, 0, [[
            'url'  => $archive_url,
            'text' => 'ニュース',
        ]]);
    }
    return $links;
}
// add_filter('wpseo_breadcrumb_links', 'mytheme_news_breadcrumb_links');

// アーカイブページのタイトルタグをカスタマイズ
function mytheme_news_archive_title( $title ) {
    if ( is_post_type_archive('news') ) {
        return 'ニュース一覧 | ' . get_bloginfo('name');
    }
    return $title;
}
add_filter('document_title_parts', function( $title ) {
    if ( is_post_type_archive('news') ) {
        $title['title'] = 'ニュース一覧';
    }
    return $title;
});

注意事項

  • flush_rewrite_rules()init フック内で毎回実行するとサイトのパフォーマンスが著しく低下します。必ず有効化・無効化フックか、パーマリンク設定ページの保存時のみ実行してください。
  • has_archive => true の場合、アーカイブスラッグは rewrite['slug'] と同じになります。スラッグを変更した後は必ずパーマリンクを再保存してください。
  • archive-news.php が存在しない場合は archive.php、さらに存在しなければ index.php が使用されます。テンプレート階層を意識して適切なファイルを作成してください。

まとめ

カスタム投稿タイプのアーカイブページを正しく表示するには、has_archive の有効化、リライトルールのフラッシュ、専用テンプレートファイルの作成の3点が重要です。pre_get_posts フィルターを活用すれば、表示件数や並び順のカスタマイズも柔軟に行えます。関連記事:WordPressのカスタムタクソノミーにカスタムフィールドを追加する方法

お気軽にご相談ください

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