2026年5月20日
2026年5月20日
WordPressのカスタムタクソノミーのテンプレートを作る方法|taxonomy-{taxonomy}.phpとターム一覧
カスタムタクソノミー(独自の分類)を作ると、https://example.com/news-category/event/ のようなターム(分類の項目)ごとの一覧ページができます。このページの見た目を変えるには、テーマにタクソノミー用のテンプレートファイルを作ります。この記事では、テンプレートファイルの名前の付け方と選ばれる順番、テンプレートの書き方、ターム一覧のナビの作り方を説明します。内容は2026年10月時点のもので、WordPress 6.9 以降を前提にしています。
例として、カスタム投稿タイプ news(ニュース)に、カテゴリー型のタクソノミー news_category(ニュースカテゴリ)を付ける場合を使います。
ステップ1:カスタムタクソノミーを登録する
テーマの functions.php(子テーマを使っている場合は子テーマの functions.php)に書きます。カスタム投稿タイプ news は別に登録してある前提です。
<?php
// functions.php
function mytheme_register_news_category(): void {
register_taxonomy(
'news_category',
array( 'news' ),
array(
'labels' => array(
'name' => 'ニュースカテゴリ',
'singular_name' => 'ニュースカテゴリ',
'all_items' => 'すべてのカテゴリ',
'edit_item' => 'カテゴリを編集',
'add_new_item' => 'カテゴリを追加',
),
'public' => true,
'hierarchical' => true, // true でカテゴリー型、false でタグ型
'show_in_rest' => true, // ブロックエディターに表示する
'show_admin_column' => true,
'rewrite' => array( 'slug' => 'news-category' ),
)
);
}
add_action( 'init', 'mytheme_register_news_category' );
show_in_rest を true にしないと、ブロックエディターの投稿画面にタクソノミーの入力欄が表示されません。
登録した後は、管理画面の「設定」→「パーマリンク設定」を開いて「変更を保存」をクリックし、URL のルール(リライトルール)を作り直します。これをしないと、ターム一覧ページが 404 になることがあります。
ステップ2:テンプレートが選ばれる順番を知る
ターム一覧ページを表示するとき、WordPress はテーマの中から次の順にファイルを探し、最初に見つかったものを使います(テンプレート階層)。表示中のタームが news_category のスラッグ event(ID 12)の場合の例です。
| 順番 | ファイル名 | 対象 |
|---|---|---|
| 1 | taxonomy-news_category-event.php |
このタームだけ(スラッグで指定) |
| 2 | taxonomy-news_category-12.php |
このタームだけ(ID で指定。WordPress 6.9 で追加) |
| 3 | taxonomy-news_category.php |
news_category のすべてのターム |
| 4 | taxonomy.php |
すべてのカスタムタクソノミー |
| 5 | archive.php |
アーカイブページ全般 |
| 6 | index.php |
すべてのページ |
スラッグが日本語の場合(例:イベント)、WordPress 4.7 以降は、デコードした日本語のファイル名 taxonomy-news_category-イベント.php が最初に探されます。ただし、日本語のファイル名はサーバーや転送ソフトの文字コードの違いで問題が起きやすいため、スラッグを英数字にするか、ID で指定する2番目の形を使うと安全です。
ふつうは3番目の taxonomy-news_category.php を1つ作れば十分です。特定のタームだけデザインを変えたい場合に、1番目か2番目を追加します。
ブロックテーマ(Twenty Twenty-Five など)では、同じ名前の HTML ファイル(例:templates/taxonomy-news_category.html)が同じ順番で探されます。この記事の PHP のテンプレートは、クラシックテーマ向けの書き方です。
ステップ3:タクソノミー用のテンプレートを作る
テーマのフォルダーに taxonomy-news_category.php を作ります。
<?php
/**
* taxonomy-news_category.php
* ニュースカテゴリのターム一覧ページ
*/
get_header();
$term = get_queried_object(); // 表示中のターム(WP_Term)
$description = term_description(); // 説明文(段落の p タグ付き)
?>
<main id="main" class="site-main">
<header class="page-header taxonomy-header">
<h1 class="page-title"><?php echo esc_html( $term->name ); ?></h1>
<?php if ( $description ) : ?>
<div class="term-description">
<?php echo wp_kses_post( $description ); ?>
</div>
<?php endif; ?>
<p class="term-count">
<?php echo esc_html( sprintf( '%s件の記事', number_format_i18n( $term->count ) ) ); ?>
</p>
</header>
<?php if ( have_posts() ) : ?>
<div class="news-grid">
<?php
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/card', 'news' );
endwhile;
?>
</div>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p>この分類の記事はまだありません。</p>
<?php endif; ?>
</main>
<?php
get_footer();
ポイントは次のとおりです。
get_queried_object()は、表示中のタームをWP_Termオブジェクトで返します。name(名前)、slug、term_id、description、countなどを使えますterm_description()は、管理画面で入力したタームの説明を、段落の<p>タグを付けて返します。説明が空なら空の文字列ですcountは、そのタームに直接付いている公開済みの投稿の数です。カテゴリー型で子タームにだけ付いている投稿は数えられませんget_template_part( 'template-parts/card', 'news' )は、テーマのtemplate-parts/card-news.phpを読み込みます。記事カードの HTML はこのファイルに書きます(なければtemplate-parts/card.phpが使われます)- このページのループには、そのタームが付いた投稿が自動で入ります。
WP_Queryを自分で書く必要はありません
ステップ4:1ページの件数を変える
ターム一覧ページの1ページあたりの件数は、「設定」→「表示設定」の「1ページに表示する最大投稿数」に従います。このタクソノミーだけ変えたい場合は、テンプレートの中で query_posts() や新しい WP_Query を使わずに、pre_get_posts でメインのクエリを変えます。こうするとページ送りも正しく動きます。
<?php
// functions.php: ニュースカテゴリの一覧ページだけ、1ページの件数を12件にする
add_action(
'pre_get_posts',
function ( WP_Query $query ): void {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_tax( 'news_category' ) ) {
$query->set( 'posts_per_page', 12 );
}
}
);
ステップ5:ターム一覧のナビを表示する
サイドバーなどに、ニュースカテゴリのタームをすべて並べるには get_terms() を使います。
<?php
// sidebar.php など: ニュースカテゴリの一覧
$news_categories = get_terms(
array(
'taxonomy' => 'news_category',
'hide_empty' => true, // 記事のないタームは出さない
'orderby' => 'name',
'order' => 'ASC',
)
);
if ( ! empty( $news_categories ) && ! is_wp_error( $news_categories ) ) : ?>
<nav class="taxonomy-nav">
<h2>カテゴリ</h2>
<ul>
<?php foreach ( $news_categories as $cat ) : ?>
<li class="<?php echo is_tax( 'news_category', $cat->term_id ) ? 'current-term' : ''; ?>">
<a href="<?php echo esc_url( get_term_link( $cat ) ); ?>">
<?php echo esc_html( $cat->name ); ?>
<span class="count">(<?php echo (int) $cat->count; ?>)</span>
</a>
</li>
<?php endforeach; ?>
</ul>
</nav>
<?php endif; ?>
hide_emptyをfalseにすると、記事のないタームも表示されますis_tax( 'news_category', $cat->term_id )は、いま表示しているターム一覧ページがそのタームのときにtrueを返します。表示中の項目に目印のクラスを付けるのに使います。2番目の引数には、ターム ID・スラッグ・名前(またはその配列)を渡しますget_term_link()は、ターム一覧ページの URL を返します
カテゴリー型で親子を字下げして表示したい場合は、wp_list_categories( array( 'taxonomy' => 'news_category', 'title_li' => '' ) ) を使うと、子タームが入れ子になった <li> の並びで出力されます(外側の <ul> は自分で書きます)。
ステップ6:投稿に付いたタームを表示する
個別の記事(single-news.php)や記事カードの中で、その投稿に付いたタームをリンクで表示します。
<?php
// single-news.php やカードのテンプレートの中: 投稿に付いたタームをリンクで表示
$terms = get_the_terms( get_the_ID(), 'news_category' );
if ( $terms && ! is_wp_error( $terms ) ) {
$links = array();
foreach ( $terms as $t ) {
$links[] = sprintf(
'<a href="%s" class="term-link">%s</a>',
esc_url( get_term_link( $t ) ),
esc_html( $t->name )
);
}
echo '<div class="post-terms">' . implode( ' ', $links ) . '</div>';
}
get_the_terms() は、タームがないときは false、エラーのときは WP_Error を返すため、両方を確かめてから使います。リンクを並べるだけなら、the_terms( get_the_ID(), 'news_category', '', ' ' ) の1行でも出力できます。
うまく表示されないときの確認
| 症状 | 確かめること |
|---|---|
| ターム一覧ページが 404 になる | 「設定」→「パーマリンク設定」で「変更を保存」したか。public が true か |
| 作ったテンプレートが使われない | ファイル名のタクソノミー名(news_category)が登録名と同じか。有効なテーマ(子テーマ)のフォルダーに置いたか |
| 記事が表示されない | 記事が公開済みで、タームが付いているか。投稿タイプが register_taxonomy() の2番目の引数に入っているか |
| 投稿画面にタームの入力欄がない | show_in_rest が true か |
どのテンプレートが使われているかは、Query Monitor などのプラグインで確かめられます。
まとめ
- タクソノミー用のテンプレートは
taxonomy-{タクソノミー名}.php。特定のタームだけ変えるならtaxonomy-{タクソノミー名}-{スラッグ}.php(6.9 以降は ID でも指定できる) - テンプレートでは
get_queried_object()で表示中のタームを取り、term_description()で説明を表示する。記事はふつうのループで表示する - 件数の変更は
pre_get_postsでメインのクエリを変える - ターム一覧は
get_terms()、URL はget_term_link()、表示中の判定はis_tax() - タクソノミーを登録した後はパーマリンク設定を保存し直す
関連記事: