2026年8月14日

2026年8月14日

WordPressでカスタムタクソノミーを作成する方法

はじめに

「カスタム投稿タイプ「ポートフォリオ」を「制作ジャンル」「使用技術」で分類したい」「カテゴリーやタグとは別の独自分類軸を設けたい」——カスタムタクソノミーを使うと、コンテンツに独自の分類体系を持たせることができます。

症状・原因

WordPressのデフォルト分類はカテゴリー(階層型)とタグ(非階層型)のみです。複数のカスタム投稿タイプに対応した独自の分類が必要な場合はregister_taxonomy()でカスタムタクソノミーを作成します。

解決手順

ステップ1:階層型タクソノミーを作成する(カテゴリー型)

// functions.php: 階層型タクソノミー「ジャンル」を登録
add_action( 'init', function() {

    $labels = [
        'name'              => 'ジャンル',
        'singular_name'     => 'ジャンル',
        'search_items'      => 'ジャンルを検索',
        'all_items'         => 'すべてのジャンル',
        'parent_item'       => '親ジャンル',
        'parent_item_colon' => '親ジャンル:',
        'edit_item'         => 'ジャンルを編集',
        'update_item'       => 'ジャンルを更新',
        'add_new_item'      => '新しいジャンルを追加',
        'new_item_name'     => '新しいジャンル名',
        'menu_name'         => 'ジャンル',
    ];

    register_taxonomy( 'genre', [ 'portfolio', 'post' ], [
        'labels'            => $labels,
        'hierarchical'      => true,          // 階層型(カテゴリー型)
        'public'            => true,
        'show_ui'           => true,
        'show_in_menu'      => true,
        'show_in_nav_menus' => true,
        'show_in_rest'      => true,          // ブロックエディタ対応
        'rewrite'           => [ 'slug' => 'genre' ],
        'show_admin_column' => true,          // 投稿一覧に列を表示
    ] );
} );

ステップ2:非階層型タクソノミーを作成する(タグ型)

// functions.php: 非階層型タクソノミー「技術スタック」を登録
add_action( 'init', function() {

    $labels = [
        'name'                       => '技術スタック',
        'singular_name'              => '技術',
        'search_items'               => '技術を検索',
        'popular_items'              => 'よく使われる技術',
        'all_items'                  => 'すべての技術',
        'edit_item'                  => '技術を編集',
        'update_item'                => '技術を更新',
        'add_new_item'               => '新しい技術を追加',
        'new_item_name'              => '新しい技術名',
        'separate_items_with_commas' => '技術をカンマで区切って入力',
        'add_or_remove_items'        => '技術を追加または削除',
        'choose_from_most_used'      => 'よく使われる技術から選択',
        'menu_name'                  => '技術スタック',
    ];

    register_taxonomy( 'tech_stack', 'portfolio', [
        'labels'            => $labels,
        'hierarchical'      => false,         // 非階層型(タグ型)
        'public'            => true,
        'show_ui'           => true,
        'show_in_rest'      => true,
        'rewrite'           => [ 'slug' => 'tech' ],
        'show_admin_column' => true,
    ] );
} );

ステップ3:タームのテンプレートを作成する

<?php
// taxonomy-genre.php: ジャンル別アーカイブテンプレート
get_header();

$term = get_queried_object(); // 現在のタームオブジェクトを取得
?>

<main class="taxonomy-archive">
    <div class="container">

        <header class="archive-header">
            <p class="taxonomy-label">ジャンル</p>
            <h1 class="archive-title">
                <?php echo esc_html( $term->name ); ?>
            </h1>

            <?php if ( $term->description ) : ?>
                <div class="term-description">
                    <?php echo wp_kses_post( $term->description ); ?>
                </div>
            <?php endif; ?>

            <p class="post-count">
                <?php echo esc_html( $term->count ); ?> 件のポートフォリオ
            </p>
        </header>

        <?php if ( have_posts() ) : ?>
            <div class="portfolio-grid">
                <?php while ( have_posts() ) : the_post(); ?>
                    <article>
                        <?php the_post_thumbnail( 'medium' ); ?>
                        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                    </article>
                <?php endwhile; ?>
            </div>

            <?php the_posts_pagination(); ?>
        <?php endif; ?>

        <!-- サブタームの一覧 -->
        <?php
        $children = get_terms( [
            'taxonomy' => 'genre',
            'parent'   => $term->term_id,
            'hide_empty' => false,
        ] );

        if ( ! empty( $children ) ) : ?>
            <div class="child-terms">
                <h2>サブジャンル</h2>
                <ul>
                    <?php foreach ( $children as $child ) : ?>
                        <li>
                            <a href="<?php echo esc_url( get_term_link( $child ) ); ?>">
                                <?php echo esc_html( $child->name ); ?>
                                (<?php echo esc_html( $child->count ); ?>)
                            </a>
                        </li>
                    <?php endforeach; ?>
                </ul>
            </div>
        <?php endif; ?>

    </div>
</main>

<?php get_footer(); ?>

ステップ4:タームメタを活用する

// functions.php: タームにカスタムデータを追加

// タームメタを保存する管理画面フォームを追加(ジャンル編集画面)
add_action( 'genre_edit_form_fields', function( $term ) {
    $color = get_term_meta( $term->term_id, 'genre_color', true );
    $icon  = get_term_meta( $term->term_id, 'genre_icon', true );
    ?>
    <tr class="form-field">
        <th><label for="genre_color">カラー</label></th>
        <td>
            <input type="color" name="genre_color" id="genre_color"
                   value="<?php echo esc_attr( $color ?: '#2271b1' ); ?>">
            <p class="description">ジャンルのテーマカラーを選択</p>
        </td>
    </tr>
    <tr class="form-field">
        <th><label for="genre_icon">アイコンクラス</label></th>
        <td>
            <input type="text" name="genre_icon" id="genre_icon"
                   value="<?php echo esc_attr( $icon ); ?>"
                   placeholder="fas fa-code">
        </td>
    </tr>
    <?php
} );

// タームメタを保存
add_action( 'edited_genre', function( $term_id ) {
    if ( isset( $_POST['genre_color'] ) ) {
        update_term_meta(
            $term_id,
            'genre_color',
            sanitize_hex_color( $_POST['genre_color'] )
        );
    }
    if ( isset( $_POST['genre_icon'] ) ) {
        update_term_meta(
            $term_id,
            'genre_icon',
            sanitize_text_field( $_POST['genre_icon'] )
        );
    }
} );

// タームメタをフロントエンドで表示
function get_genre_color( $term_id ) {
    $color = get_term_meta( $term_id, 'genre_color', true );
    return $color ?: '#2271b1';
}

ステップ5:タクソノミーの便利な関数を活用する

// よく使うタクソノミー関連関数

// 投稿に紐づくタームを取得
$genres = get_the_terms( get_the_ID(), 'genre' );
if ( $genres && ! is_wp_error( $genres ) ) {
    foreach ( $genres as $genre ) {
        echo '<a href="' . esc_url( get_term_link( $genre ) ) . '">'
           . esc_html( $genre->name ) . '</a>';
    }
}

// タクソノミーの全タームを取得
$all_genres = get_terms( [
    'taxonomy'   => 'genre',
    'hide_empty' => false,
    'orderby'    => 'count',
    'order'      => 'DESC',
] );

// 特定タームに紐づく投稿を取得
$query = new WP_Query( [
    'post_type'  => 'portfolio',
    'tax_query'  => [
        [
            'taxonomy' => 'genre',
            'field'    => 'slug',
            'terms'    => [ 'web-design', 'branding' ],
            'operator' => 'IN', // IN / NOT IN / AND
        ],
    ],
] );

// 複数タクソノミーで絞り込み
$query = new WP_Query( [
    'post_type' => 'portfolio',
    'tax_query' => [
        'relation' => 'AND', // AND: 両方を満たす / OR: どちらかを満たす
        [
            'taxonomy' => 'genre',
            'field'    => 'slug',
            'terms'    => 'web-design',
        ],
        [
            'taxonomy' => 'tech_stack',
            'field'    => 'slug',
            'terms'    => 'react',
        ],
    ],
] );

注意事項

  • register_taxonomy()register_post_type()と同じくinitフックで呼び出してください。タクソノミーをカスタム投稿タイプに紐づける場合は、投稿タイプの登録後に登録するか、register_post_type()taxonomies引数で指定します。
  • タームのパーマリンクが404になる場合は、カスタム投稿タイプと同様にパーマリンク設定を再保存してください。
  • show_in_rest: trueを設定しないとブロックエディタのサイドバーにタクソノミーが表示されません。

まとめ

カスタムタクソノミーは「register_taxonomy()で階層型・非階層型を選択して登録→投稿タイプと紐付け→taxonomy-{taxonomy}.phpでアーカイブテンプレート作成→update_term_meta/get_term_metaでタームメタを活用→tax_queryで複合条件クエリ」の流れで構築します。関連記事:WordPressでカスタム投稿タイプを作成する方法ACFでWordPressにカスタムフィールドを追加する方法

お気軽にご相談ください

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