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_archive と rewrite を正しく設定します。has_archive を true にするか、アーカイブのスラッグを文字列で指定します。
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のカスタムタクソノミーにカスタムフィールドを追加する方法