2026年6月22日

2026年6月22日

WordPressのカスタムタクソノミーにカスタムフィールドを追加する方法

はじめに

WordPressのカスタムタクソノミーでは、標準ではタームに名前・スラッグ・説明文しか持てません。しかし、カテゴリーにアイコン画像やカラーコードなど独自の情報を持たせたい場合があります。この記事では、カスタムタクソノミーのタームにカスタムフィールドを追加する方法を5ステップで解説します。

症状・原因

  • カスタムタクソノミーの編集画面に独自の入力フィールドを追加したいが方法がわからない
  • add_term_meta()update_term_meta() の使い方が投稿メタと異なり混乱する
  • フロントエンドでタームのカスタムフィールド値を取得する方法がわからない
  • ターム一覧でメタ値を使ったフィルタリングやソートを実装したい

解決手順

ステップ1:カスタムタクソノミーを登録する

まず、カスタムフィールドを追加したいタクソノミーを register_taxonomy() で登録します。

function mytheme_register_taxonomy() {
    $labels = [
        'name'              => 'ニュースカテゴリー',
        'singular_name'     => 'ニュースカテゴリー',
        'search_items'      => 'カテゴリーを検索',
        'all_items'         => 'すべてのカテゴリー',
        'edit_item'         => 'カテゴリーを編集',
        'add_new_item'      => '新規カテゴリーを追加',
        'new_item_name'     => '新しいカテゴリー名',
    ];

    $args = [
        'labels'            => $labels,
        'hierarchical'      => true,    // カテゴリー形式(falseでタグ形式)
        'public'            => true,
        'show_ui'           => true,
        'show_admin_column' => true,    // 投稿一覧に表示
        'show_in_rest'      => true,    // Gutenberg対応
        'rewrite'           => ['slug' => 'news-category'],
    ];

    // 'news'投稿タイプに関連付け
    register_taxonomy('news_category', ['news'], $args);
}
add_action('init', 'mytheme_register_taxonomy');

ステップ2:タームの追加・編集フォームにカスタムフィールドを表示する

{taxonomy}_add_form_fields アクションで「新規追加」フォームに、{taxonomy}_edit_form_fields アクションで「編集」フォームにフィールドを追加します。

// 新規タームの追加フォームにフィールドを追加
function mytheme_news_category_add_fields( $taxonomy ) {
    ?>
    <div class="form-field term-color-wrap">
        <label for="term-color">カテゴリーカラー</label>
        <input type="color"
               name="news_category_color"
               id="term-color"
               value="#0073aa">
        <p>カテゴリーの識別カラーを選択してください。</p>
    </div>
    <div class="form-field term-icon-wrap">
        <label for="term-icon">アイコン(絵文字またはDashicon)</label>
        <input type="text"
               name="news_category_icon"
               id="term-icon"
               value=""
               placeholder="例: 📰 または dashicons-megaphone">
        <p>アーカイブページのヘッダーに表示されます。</p>
    </div>
    <?php
}
add_action('news_category_add_form_fields', 'mytheme_news_category_add_fields');

// 既存タームの編集フォームにフィールドを追加
function mytheme_news_category_edit_fields( $term, $taxonomy ) {
    // 既存のメタ値を取得
    $color = get_term_meta($term->term_id, 'news_category_color', true);
    $icon  = get_term_meta($term->term_id, 'news_category_icon', true);
    ?>
    <tr class="form-field term-color-wrap">
        <th scope="row">
            <label for="term-color">カテゴリーカラー</label>
        </th>
        <td>
            <input type="color"
                   name="news_category_color"
                   id="term-color"
                   value="<?php echo esc_attr($color ?: '#0073aa'); ?>">
            <p class="description">カテゴリーの識別カラーを選択してください。</p>
        </td>
    </tr>
    <tr class="form-field term-icon-wrap">
        <th scope="row">
            <label for="term-icon">アイコン</label>
        </th>
        <td>
            <input type="text"
                   name="news_category_icon"
                   id="term-icon"
                   value="<?php echo esc_attr($icon); ?>"
                   placeholder="例: 📰">
            <p class="description">アーカイブページのヘッダーに表示されます。</p>
        </td>
    </tr>
    <?php
}
add_action('news_category_edit_form_fields', 'mytheme_news_category_edit_fields', 10, 2);

ステップ3:フォームの送信時にメタデータを保存する

create_{taxonomy} アクションで新規作成時に、edit_{taxonomy} アクションで更新時にメタデータを保存します。

// 新規ターム作成時の保存
function mytheme_save_news_category_meta( $term_id ) {
    // nonceチェック(セキュリティ)
    // ※フォームにwp_nonce_field()を追加している前提
    if ( isset($_POST['news_category_nonce']) &&
         ! wp_verify_nonce($_POST['news_category_nonce'], 'save_news_category_meta') ) {
        return;
    }

    // カラーの保存
    if ( isset($_POST['news_category_color']) ) {
        $color = sanitize_hex_color($_POST['news_category_color']);
        update_term_meta($term_id, 'news_category_color', $color);
    }

    // アイコンの保存
    if ( isset($_POST['news_category_icon']) ) {
        $icon = sanitize_text_field($_POST['news_category_icon']);
        update_term_meta($term_id, 'news_category_icon', $icon);
    }
}
// 新規作成時
add_action('create_news_category', 'mytheme_save_news_category_meta');
// 編集・更新時
add_action('edit_news_category', 'mytheme_save_news_category_meta');

// メタデータ削除(ターム削除時)
function mytheme_delete_news_category_meta( $term_id ) {
    delete_term_meta($term_id, 'news_category_color');
    delete_term_meta($term_id, 'news_category_icon');
}
add_action('delete_news_category', 'mytheme_delete_news_category_meta');

ステップ4:フロントエンドでタームメタを表示する

get_term_meta() を使ってカスタムフィールドの値を取得し、テンプレートに表示します。

// タクソノミーアーカイブページでの表示例
function mytheme_display_term_meta() {
    if ( ! is_tax('news_category') ) {
        return;
    }

    $term = get_queried_object();

    // タームのカスタムフィールドを取得
    $color = get_term_meta($term->term_id, 'news_category_color', true);
    $icon  = get_term_meta($term->term_id, 'news_category_icon', true);

    // デフォルト値の設定
    $color = $color ?: '#0073aa';
    $icon  = $icon  ?: '📰';

    printf(
        '<div class="archive-header" style="border-left: 4px solid %s;">
            <span class="term-icon">%s</span>
            <h1 class="archive-title">%s</h1>
            <p class="archive-description">%s</p>
        </div>',
        esc_attr($color),
        esc_html($icon),
        esc_html($term->name),
        esc_html($term->description)
    );
}

// 投稿一覧でタームのカスタムフィールドを取得する例
function mytheme_get_post_category_color( $post_id ) {
    $terms = get_the_terms($post_id, 'news_category');

    if ( empty($terms) || is_wp_error($terms) ) {
        return '#cccccc';
    }

    // 最初のタームのカラーを取得
    $primary_term = $terms[0];
    $color = get_term_meta($primary_term->term_id, 'news_category_color', true);

    return $color ?: '#0073aa';
}

ステップ5:WP_Term_Query でタームメタを使ってフィルタリングする

WP_Term_Querymeta_query パラメーターを使って、カスタムフィールドの値でタームを絞り込みます。

// 特定のカラーが設定されているタームを取得
function mytheme_get_colored_terms( $color = null ) {
    $query_args = [
        'taxonomy'   => 'news_category',
        'hide_empty' => false,
        'orderby'    => 'name',
    ];

    // カラーでフィルタリング
    if ( $color ) {
        $query_args['meta_query'] = [
            [
                'key'     => 'news_category_color',
                'value'   => $color,
                'compare' => '=',
            ],
        ];
    } else {
        // カラーが設定されているタームのみ
        $query_args['meta_query'] = [
            [
                'key'     => 'news_category_color',
                'compare' => 'EXISTS',
            ],
        ];
    }

    $term_query = new WP_Term_Query($query_args);
    return $term_query->get_terms();
}

// 使用例:カラー付きのカテゴリー一覧を表示
$colored_terms = mytheme_get_colored_terms();
foreach ( $colored_terms as $term ) {
    $color = get_term_meta($term->term_id, 'news_category_color', true);
    $icon  = get_term_meta($term->term_id, 'news_category_icon', true);
    echo '<a href="' . get_term_link($term) . '" style="color:' . esc_attr($color) . '">';
    echo esc_html($icon) . ' ' . esc_html($term->name);
    echo '</a>';
}

注意事項

  • タームメタを保存する際は必ず sanitize_hex_color()sanitize_text_field() などで入力値をサニタイズしてください。XSS攻撃の原因になります。
  • get_term_meta() の第3引数を true にすると単一値、false または省略すると配列で返ります。単一値フィールドは必ず true を指定してください。
  • ターム削除時にメタデータが残ることがあります。delete_{taxonomy} アクションフックで必ず削除処理を実装してください。

まとめ

カスタムタクソノミーへのカスタムフィールド追加は、add_form_fieldsedit_form_fields アクションでUIを追加し、create_{taxonomy}edit_{taxonomy} アクションで update_term_meta() を使って保存するのが基本パターンです。関連記事:WordPressのWP_Queryメタクエリを最適化してデータベース負荷を軽減する方法

お気軽にご相談ください

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