WordPressのタクソノミーとタームをマスターする

タクソノミー、タームとは?

『タクソノミー』は「分類」を意味する言葉で、WordPress では投稿などをグループ化するための仕組みを指します。WordPress ではあらかじめ「カテゴリー」や「投稿タグ」といったタクソノミーが用意されています。ユーザーが独自に追加するタクソノミーはカスタムタクソノミーと呼ばれ、Custom Post Type UI などのプラグインを利用して登録することが多いと思います。

タクソノミー内のさまざまなグループ名は『ターム(項目)』と呼ばれます。例えば管理画面の「新規カテゴリーを追加」から追加されるのが『ターム』になります。

WP_Term クラス と WP_Taxonomy クラス

タクソノミー/タームについて理解するために WP_Term クラスと WP_Taxonomy クラスについて知っておく必要があります。ここではそれぞれのクラスのプロパティについてまとめます。

WP_Term クラスのプロパティ

WP_Taxonomy クラスよりも重要度が高いのがこちらの WP_Term クラスです。

プロパティ名 説明
term_id int タームID
name string ターム名
slug string タームスラッグ
term_group int タームグループ
term_taxonomy_id int タームタクソノミーID
taxonomy string タームのタクソノミー名
description string タームの説明
parent int 親タームのタームID
count int タームに関連するオブジェクト数
filter string タームオブジェクトのサニタイズレベル

WP_Taxonomy クラスのプロパティ

WP_Term よりも重要度が低いため、このクラスの中身を知らなくてもいいことが多いと思います。

プロパティ名 説明
name string タクソノミー名
label string メニューに表示されるタクソノミー名
labels stdClass タクソノミーのラベルオブジェクト
description string タクソノミーの説明
public bool 管理画面やフロントエンドでの公開利用を目的としているかどうか
publicly_queryable bool 公開クエリ可能かどうか
hierarchical bool 階層を持つかどうか
show_ui bool タームを追加/編集/削除するためのUIを管理画面に追加するかどうか
show_in_menu bool 管理画面のメニューに表示するかどうか
show_in_nav_menus bool ナビゲーションメニューの選択肢に追加するかどうか
show_tagcloud bool タグクラウドを利用するかどうか
show_in_quick_edit bool クイック編集/一括編集パネルに表示するかどうか
show_admin_column bool 関連づけられた投稿の一覧画面にカラムを追加するかどうか
meta_box_cb bool|callable メタボックスに表示させるときのコールバック関数

タクソノミー/タームに関連する関数

テーマやプラグインを開発する際に利用される、タクソノミー/ターム関連の関数をまとめました。これらの関数は

で定義されています。場面に応じた関数のまとめは次のようになります。

したいこと 使う関数
ターム一覧が欲しい get_terms
名前やスラッグを元にタームの情報が欲しい get_term_by
タームの子孫タームが欲しい get_term_children
タームが親子関係にあるかを知りたい term_is_ancestor_of
タームのパンくずリストが作りたい get_term_parents_list
パンくずリストをつくるので祖先ターム一覧が欲しい get_ancestors
投稿に関連づけられたターム一覧が欲しい get_the_terms
オブジェクトに関連づけられたターム一覧が欲しい wp_get_object_terms
投稿がタームに紐づいているかどうか知りたい has_term
オブジェクトがタームに紐づいているかどうか知りたい is_object_in_term
タクソノミーアーカイブページのパーマリンクが欲しい get_term_link

the_taxonomies

ループ内で使用すれば投稿に紐づいたタクソノミーをリンク付きで表示します。ループ外であれば $argspost キーに投稿ID/投稿オブジェクトを渡すことでその投稿に紐づいたタクソノミーをリンク付きで表示します。

// wp-includes/taxonomy.php

/**
 * @param array $args {
 *     Arguments about which post to use and how to format the output. Shares all of the arguments
 *     supported by get_the_taxonomies(), in addition to the following.
 *
 *     @type  int|WP_Post $post   Post ID or object to get taxonomies of. Default current post.
 *     @type  string      $before Displays before the taxonomies. Default empty string.
 *     @type  string      $sep    Separates each taxonomy. Default is a space.
 *     @type  string      $after  Displays after the taxonomies. Default empty string.
 * }
 */
the_taxonomies( array $args = array() )

https://developer.wordpress.org/reference/functions/the_taxonomies/

get_taxonomy

タクソノミーオブジェクトを取得します。

// wp-includes/taxonomy.php

/**
 * @param string $taxonomy Name of taxonomy object to return.
 * @return WP_Taxonomy|false The Taxonomy Object or false if $taxonomy doesn't exist.
 */
get_taxonomy( string $taxonomy )

https://developer.wordpress.org/reference/functions/get_taxonomy/

get_terms

指定したタクソノミーに含まれるターム情報を取得し、WP_Term の配列として返します。Codex 日本語版 では第2引数に $args を渡していますが、これは古い書き方ですので注意してください。

// wp-includes/taxonomy.php

/**
 * @param array|string $args       Optional. Array or string of arguments. See WP_Term_Query::__construct()
 *                                 for information on accepted arguments. Default empty array.
 * @param array|string $deprecated Optional. Argument array, when using the legacy function parameter format.
 *                                 If present, this parameter will be interpreted as `$args`, and the first
 *                                 function parameter will be parsed as a taxonomy or array of taxonomies.
 *                                 Default empty.
 * @return WP_Term[]|int[]|string[]|string|WP_Error Array of terms, a count thereof as a numeric string,
 *                                                  or WP_Error if any of the taxonomies do not exist.
 *                                                  See the function description for more information.
 */
get_terms( array|string $args = array(), array|string $deprecated = '' )

https://developer.wordpress.org/reference/functions/get_terms/

引数 $args に渡すのは WP_Term_Query のコンストラクタに渡す引数と同じになっています。

get_posts    <=> WP_Query
get_terms    <=> WP_Term_Query
get_comments <=> WP_Comment_Query

という対応関係にあることを覚えておくといいと思います。

get_term

タームIDからターム情報を取得します。関数内に get_term フックと get_{$taxonomy} フックが用意されているため、タームオブジェクトをフィルターする際に利用されます。

// wp-includes/taxonomy.php

/**
 * @param int|WP_Term|object $term     If integer, term data will be fetched from the database,
 *                                     or from the cache if available.
 *                                     If stdClass object (as in the results of a database query),
 *                                     will apply filters and return a `WP_Term` object with the `$term` data.
 *                                     If `WP_Term`, will return `$term`.
 * @param string             $taxonomy Optional. Taxonomy name that `$term` is part of.
 * @param string             $output   Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
 *                                     correspond to a WP_Term object, an associative array, or a numeric array,
 *                                     respectively. Default OBJECT.
 * @param string             $filter   Optional. How to sanitize term fields. Default 'raw'.
 * @return WP_Term|array|WP_Error|null WP_Term instance (or array) on success, depending on the `$output` value.
 *                                     WP_Error if `$taxonomy` does not exist. Null for miscellaneous failure.
 */
get_term( int|WP_Term|object $term, string $taxonomy = '', string $output = OBJECT, string $filter = 'raw' )

https://developer.wordpress.org/reference/functions/get_term/

get_term_by

タームのスラッグ/名前/ID/term_taxonomy_id からターム情報を取得します。内部では get_term を呼び出しています。get_term はタームのスラッグや名前をもとに呼び出せないため、get_term よりもずっと使いやすい関数になっています。

// wp-includes/taxonomy.php

/**
 * @param string     $field    Either 'slug', 'name', 'id' or 'ID' (term_id), or 'term_taxonomy_id'.
 * @param string|int $value    Search for this term value.
 * @param string     $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'.
 * @param string     $output   Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
 *                             correspond to a WP_Term object, an associative array, or a numeric array,
 *                             respectively. Default OBJECT.
 * @param string     $filter   Optional. How to sanitize term fields. Default 'raw'.
 * @return WP_Term|array|false WP_Term instance (or array) on success, depending on the `$output` value.
 *                             False if `$taxonomy` does not exist or `$term` was not found.
 */
get_term_by( string $field, string|int $value, string $taxonomy = '', string $output = OBJECT, string $filter = 'raw' )

https://developer.wordpress.org/reference/functions/get_term_by/

get_term_children

タームIDで指定されるタームの子孫タームのIDを配列として返します。関数内で再帰的に呼び出されているため、直接の子タームだけでなく子孫タームすべてを取得します。

// wp-includes/taxonomy.php

/**
 * @param int    $term_id  ID of Term to get children.
 * @param string $taxonomy Taxonomy Name.
 * @return array|WP_Error List of Term IDs. WP_Error returned if `$taxonomy` does not exist.
 */
get_term_children( int $term_id, string $taxonomy )

https://developer.wordpress.org/reference/functions/get_term_children/

term_exists

タクソノミータームが存在するかどうかを返します。戻り値は bool ではありません。タームが存在しなければ null を、呼び出し時にタクソノミーが渡されずにタームが存在した場合は タームIDを、タクソノミーが渡されてタームが存在した場合はタームIDとタームタクソノミーID (term_taxonomy_id) が配列として返されます。

/**
 * @param int|string $term     The term to check. Accepts term ID, slug, or name.
 * @param string     $taxonomy Optional. The taxonomy name to use.
 * @param int        $parent   Optional. ID of parent term under which to confine the exists search.
 * @return mixed Returns null if the term does not exist.
 *               Returns the term ID if no taxonomy is specified and the term ID exists.
 *               Returns an array of the term ID and the term taxonomy ID if the taxonomy is specified and the pairing exists.
 *               Returns 0 if term ID 0 is passed to the function.
 */
term_exists( int|string $term, string $taxonomy = '', int $parent = null )

https://developer.wordpress.org/reference/functions/term_exists/

term_is_ancestor_of

第一引数に渡されるタームが第二引数に渡されるタームの先祖かどうかを返します。この関数は関数内部で再帰的に呼び出されるため、直接の親子関係だけではなく先祖・子孫関係にあるかどうかを調べることができます。

/**
 * @param int|object $term1    ID or object to check if this is the parent term.
 * @param int|object $term2    The child term.
 * @param string     $taxonomy Taxonomy name that $term1 and `$term2` belong to.
 * @return bool Whether `$term2` is a child of `$term1`.
 */
term_is_ancestor_of( int|object $term1, int|object $term2, string $taxonomy )

https://developer.wordpress.org/reference/functions/term_is_ancestor_of/

wp_get_object_terms

与えられたオブジェクト(投稿など)に関連づけられたタームを取得して配列として返します。オブジェクトは複数でも構いません。同じような関数に wp_get_post_terms がありますが、こちらは $taxonomies = 'post_tag' として 内部で wp_get_object_terms を呼び出しているだけであまり使わないと思います。

// wp-includes/taxonomy.php

/**
 * @param int|int[]       $object_ids The ID(s) of the object(s) to retrieve.
 * @param string|string[] $taxonomies The taxonomy names to retrieve terms from.
 * @param array|string    $args       See WP_Term_Query::__construct() for supported arguments.
 * @return WP_Term[]|WP_Error Array of terms or empty array if no terms found.
 *                            WP_Error if any of the taxonomies don't exist.
 */
wp_get_object_terms( int|int[] $object_ids, string|string[] $taxonomies, array|string $args = array() )

https://developer.wordpress.org/reference/functions/wp_get_object_terms/

get_term_link

タクソノミーアーカイブページへのパーマリンクを返します。get_the_term_list 関数内から呼び出されています。

// wp-includes/taxonomy.php

/**
 * @param WP_Term|int|string $term     The term object, ID, or slug whose link will be retrieved.
 * @param string             $taxonomy Optional. Taxonomy. Default empty.
 * @return string|WP_Error URL of the taxonomy term archive on success, WP_Error if term does not exist.
 */
get_term_link( WP_Term|int|string $term, string $taxonomy = '' )

https://developer.wordpress.org/reference/functions/the_terms/

is_object_in_term

与えられたオブジェクト(投稿など)が与えられたタームに紐づいているかどうかを返します。タームはタームIDや名前、スラッグの配列として与えることができます。

// wp-includes/taxonomy.php

/**
 * @param int                       $object_id ID of the object (post ID, link ID, ...).
 * @param string                    $taxonomy  Single taxonomy name.
 * @param int|string|int[]|string[] $terms     Optional. Term ID, name, slug, or array of such
 *                                             to check against. Default null.
 * @return bool|WP_Error WP_Error on input error.
 */
is_object_in_term( int $object_id, string $taxonomy, int|string|int[]|string[] $terms = null )

https://developer.wordpress.org/reference/functions/is_object_in_term/

get_ancestors

与えられたオブジェクトの祖先オブジェクトのIDを配列として返します。配列は階層が近いものから遠いもの順になっています。例えば $object_id にタームID、$object_type にタクソノミー名、$resource_typetaxonomy を与えると、祖先タームのID配列を取得することができます。タクソノミーのぱんくずリストを作成する際に役に立つ関数です。

// wp-includes/taxonomy.php

/**
 * @param int    $object_id     Optional. The ID of the object. Default 0.
 * @param string $object_type   Optional. The type of object for which we'll be retrieving
 *                              ancestors. Accepts a post type or a taxonomy name. Default empty.
 * @param string $resource_type Optional. Type of resource $object_type is. Accepts 'post_type'
 *                              or 'taxonomy'. Default empty.
 * @return int[] An array of IDs of ancestors from lowest to highest in the hierarchy.
 */
get_ancestors( int $object_id, string $object_type = '', string $resource_type = '' )

https://developer.wordpress.org/reference/functions/get_ancestors/

get_the_terms

投稿や固定ページが属するタクソノミーのターム一覧を取得して WP_Term の配列として返します。関数内部で wp_get_object_terms を呼び出しています。

// wp-includes/category-template.php

/**
 * @param int|WP_Post $post     Post ID or object.
 * @param string      $taxonomy Taxonomy name.
 * @return WP_Term[]|false|WP_Error Array of WP_Term objects on success, false if there are no terms
 *                                  or the post does not exist, WP_Error on failure.
 */
get_the_terms( int|WP_Post $post, string $taxonomy )

https://developer.wordpress.org/reference/functions/get_the_terms/

get_the_term_list

投稿や固定ページにつけられたターム一覧を出力するための HTML を返します。the_terms 関数内から呼び出されています。term_links-{$taxonomy} というフィルターも用意されています。タグ一覧を出力するのに使えます。

// wp-includes/category-template.php

/**
 * @param int    $post_id  Post ID.
 * @param string $taxonomy Taxonomy name.
 * @param string $before   Optional. String to use before the terms. Default empty.
 * @param string $sep      Optional. String to use between the terms. Default empty.
 * @param string $after    Optional. String to use after the terms. Default empty.
 * @return string|false|WP_Error A list of terms on success, false if there are no terms,
 *                               WP_Error on failure.
 */
get_the_term_list( int $post_id, string $taxonomy, string $before = '', string $sep = '', string $after = '' )

https://developer.wordpress.org/reference/functions/get_the_term_list/

get_term_parents_list

IDで与えられたタームの祖先タームのリンク付きリストの HTML 文字列を取得します。パンくずリストにそのまま使えます。

// wp-includes/category-template.php

/**
 * @param int          $term_id  Term ID.
 * @param string       $taxonomy Taxonomy name.
 * @param string|array $args {
 *     Array of optional arguments.
 *
 *     @type string $format    Use term names or slugs for display. Accepts 'name' or 'slug'.
 *                             Default 'name'.
 *     @type string $separator Separator for between the terms. Default '/'.
 *     @type bool   $link      Whether to format as a link. Default true.
 *     @type bool   $inclusive Include the term to get the parents for. Default true.
 * }
 * @return string|WP_Error A list of term parents on success, WP_Error or empty string on failure.
 */
get_term_parents_list( int $term_id, string $taxonomy, string|array $args = array() )

https://developer.wordpress.org/reference/functions/get_term_parents_list/

the_terms

投稿や固定ページにつけられたターム一覧を出力します。テーマのテンプレート内で利用することが多いと思います。

// wp-includes/category-template.php

/**
 * @param int    $post_id  Post ID.
 * @param string $taxonomy Taxonomy name.
 * @param string $before   Optional. String to use before the terms. Default empty.
 * @param string $sep      Optional. String to use between the terms. Default ', '.
 * @param string $after    Optional. String to use after the terms. Default empty.
 * @return void|false Void on success, false on failure.
 */
the_terms( int $post_id, string $taxonomy, string $before = '', string $sep = ', ', string $after = '' )

https://developer.wordpress.org/reference/functions/the_terms/

has_term

与えられたタームが投稿に紐づいているかどうかを返します。関数内部では is_object_in_term を呼び出しています。

// wp-includes/category-template.php

/**
 * @param string|int|array $term     Optional. The term name/term_id/slug,
 *                                   or an array of them to check for. Default empty.
 * @param string           $taxonomy Optional. Taxonomy name. Default empty.
 * @param int|WP_Post      $post     Optional. Post to check instead of the current post.
 * @return bool True if the current post has any of the given terms
 *              (or any term, if no term specified). False otherwise.
 */
function has_term( $term = '', $taxonomy = '', $post = null )

https://developer.wordpress.org/reference/functions/has_term/

single_term_title

タクソノミータームのアーカイブページでページタイトルを取得、または表示します。

// wp-includes/general-template.php

/**
 * @param string $prefix  Optional. What to display before the title.
 * @param bool   $display Optional. Whether to display or retrieve title. Default true.
 * @return string|void Title when retrieving.
 */
single_term_title( string $prefix = '', bool $display = true )

https://developer.wordpress.org/reference/functions/single_term_title/

その他あると便利かもしれない関数

親タームから子ターム一覧(孫を含めない)を取得する

孫タームを含めないような場合は get_term_children で全子孫タームを取得しておいて wp_list_filter でフィルターします。

/**
 * 親タームから子ターム一覧(孫を含めない)を取得する.
 *
 * @param int    $term_id  ID of Term to get children.
 * @param string $taxonomy Taxonomy Name.
 * @return array|WP_Error List of Term IDs. WP_Error returned if `$taxonomy` does not exist.
 */
function get_direct_term_children( int $term_id, string $taxonomy ) {
    return wp_list_filter( get_term_children( $term_id, $taxonomy ), array( 'parent' => $term_id ) );
}

タクソノミーとタームについて知っておきたいこと

WordPress では taxonomy_id は存在しない

WordPress では多くの情報がデータベース上に保存されています。例えば投稿や固定ページは wp_posts テーブルに保存されていて、連番のIDが割り振られています。そしてカスタムフィールドは wp_postmeta テーブルに保存されていて、post_id カラムに入っている投稿IDを通して投稿や固定ページと紐づけられています。

タクソノミーについてどうかというと、WordPress では wp_taxonomies のようなテーブルがあってそこでタクソノミーIDが連番で振られていて、タームを保存する wp_terms の中で taxonomy_id カラムで参照されている…というようなことにはなっていません。

WordPress ではタクソノミーは $wp_taxonomies というグローバル変数に保存されています。これは例えば wp-includes/taxonomy.php で定義されている get_taxonomies ー この関数は登録されたタクソノミーの一覧を取得します ー を見ると明らかです。

function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) {
    global $wp_taxonomies;

    $field = ( 'names' === $output ) ? 'name' : false;

    return wp_filter_object_list( $wp_taxonomies, $args, $operator, $field );
}

グローバル変数である $wp_taxonomies には register_taxonomy が呼ばれた際にタクソノミー情報が登録されます。そしてデフォルトの状態では、init フックに登録されている create_initial_taxonomies 関数(この関数は wp-includes/taxonomy.php で定義されています)内で category (カテゴリー)、post_tag (投稿タグ)、post_format (投稿フォーマット) などが登録されます。

タームに関連するデータベーステーブル

タクソノミーはデータベースに保存されるのではなくグローバル変数として扱われることを見ましたが、タームはデータベース内の wp_terms テーブルに保存されています。ターム名もタームスラッグもインデックスされています。

カラム 種別 Null キー (キー名) 初期値 備考 説明
term_id bigint(20) unsigned PRIMARY (PRIMARY) AUTO_INCREMENT タームID
name varchar(200) INDEX (name) ターム名
slug varchar(200) UNIQUE (slug) タームスラッグ
term_group bigint(10) 0 類義語のグルーピング

このテーブルで重要なことは、term_order のような順番を制御できるようなカラムがないことです。つまりデフォルト状態の WordPress ではタクソノミーのタームを順序づけることはできません。タームの並び替えを可能にするようなプラグイン、例えば Intuitive Custom Post Order などでは wp_terms テーブルに term_order のようなカラムを追加することで並び替えを実現しています。

次にタームとタクソノミーを結びつけるテーブルである wp_term_taxonomy があります。

カラム 種別 Null キー (キー名) 初期値 備考 説明
term_taxonomy_id bigint(20) unsigned PRIMARY (PRIMARY) AUTO_INCREMENT ターム+タクソノミーペアの固有ID
term_id bigint(20) unsigned UNIQUE (term_id_taxonomy) 0 wp_terms テーブルの term_id
taxonomy varchar(32) UNIQUE (term_id_taxonomy) & INDEX (taxonomy) タームが属するタクソノミー
description longtext タームの説明
parent bigint(20) unsigned 0 wp_terms テーブルの term_id
count bigint(20) 0 ターム+タクソノミーペアに関連づけられたオブジェクト数(カテゴリなら属する投稿記事数)

3つ目はタームと投稿(固定ページなどを含む)を結びつける wp_term_relationships テーブルです。

カラム 種別 Null キー (キー名) 初期値 備考 説明
object_id bigint(20) unsigned PRIMARY (PRIMARY) 記事ID or リンクID
term_taxonomy_id bigint(20) unsigned PRIMARY (PRIMARY) & INDEX (term_taxonomy_id) term_taxonomyterm_taxonomy_id
term_order bigint(11)

最後は wp_termmeta テーブルです。ターム用のカスタムフィールド(メタ情報)を保存するためにあります。

カラム 種別 Null キー (キー名) 初期値 備考 説明
meta_id bigint(20) unsigned PRIMARY (PRIMARY) AUTO_INCREMENT タームID
term_id bigint(20) unsigned INDEX (term_id) 0 term_taxonomyterm_taxonomy_id
meta_key varchar(255) YES NULL INDEX (meta_key) カスタムフィールドのキー名
meta_value longtext YES NULL カスタムフィールドの値
引用元: https://codex.wordpress.org/

タクソノミーとカスタムフィールドとの使い分け

投稿やカスタム投稿に対して何かしらの条件を課して絞り込み検索をするような場合、カスタムフィールドを用いて次のようなクエリを書きたくなるかもしれません。

<?php
$args = array(
    'post_type'  => 'product',
    'meta_query' => array(
        array(
            'key'     => 'color',
            'value'   => 'blue',
        )
    )
);

$query = new WP_Query( $args );

データベース内のレコード数が数百〜数千くらいの少ない場合であればこれでも構いませんが、数十万、数百万のレコードを扱うような場合には上記のようなカスタムフィールドを用いた絞り込みはNGになります。これは wp_postmeta テーブルの meta_value フィールドがインデックスされていないからです。こういった場合はカスタムフィールドで検索条件を扱うのではなく、タクソノミーを利用する方が良いパフォーマンスが得られます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です