WordPress

WordPress のタクソノミーを親子順に並べる

TABLEofCONTENTS

ビルトイン関数で実現する方法と、並び順を変更するプラグインを紹介します。

記事に属しているタームを取得する

以下の関数で、指定した記事に属しているタクソノミーのターム配列を取得できます。

なお、上2つは内部で wp_get_object_terms() を利用しています。下2つは オプション を指定することができます。

wp_get_post_terms() の引数 $post_id が optional でデフォルト値「0」になっていますが、「0」を与えると空配列を返されて何も取得できないので気をつけましょう。

タームの親子関係を保持して表示する

WordPress には、階層(ツリー, 木)構造を持つデータ(オブジェクト)の親子関係を保持しつつ HTML を作成するためのクラスが用意されています。タクソノミー関連では以下のクラスがあります。

これらはすべて抽象クラス Walker の派生クラスです。これらのクラスを直接利用する必要は無く、各々以下の関数で利用できます。

walk_category_* 関数に先ほどの関数で取得したタームオブジェクトの配列を渡すと、親子関係が保持された HTML(文字列)を取得できます。第3引数のオプションは省略すると Notice になるので必ず指定します。

$terms = get_the_terms( $post, 'my_taxonomy' );
if ( $terms && ! is_wp_error( $terms ) ) {
  echo walk_category_tree( $terms, 0, array(
    'use_desc_for_title' => false,
    'style' => 'list',
) );
}
<select>
<?php
$terms = wp_get_object_terms( $post->ID, 'my_taxonomy' );
if ( $terms && ! is_wp_error( $terms ) ) {
  echo walk_category_dropdown_tree( $terms, 0, array(
    'show_count' => false,
    'selected'   => 0,      // selected term id
  ) );
}
?>
</select>

ターム取得に失敗した場合(タクソノミーが存在しない等)各関数は false, array(), WP_Errorオブジェクトのいずれかを返します。取得成功を前提にしていると予期せぬ不具合に見舞われることがあるため、成否判定と必要なら例外処理を入れるようにしましょう。

全タームの親子関係を保持して表示する

リスト, ドロップダウン

get_terms() で全タームを取得して、タームの親子関係を保持して表示する と同様に … とややこしいことをしなくても、以下のビルトイン関数でできます。

全タームの取得には 'hide_empty' => false が慣習的に指定されがちですが 'get' => 'all' の方が意味的に良いように思います。

チェックボックス

チェックボックスの HTML も取得可能です。下記の Walker 派生クラスと専用の関数が用意されています。

これらは wp-admin/includes/template.php 内で定義されているため、公開画面側で利用するには予めインクルードしておく必要があります。

include_once( ABSPATH . 'wp-admin/includes/template.php' );
echo '<ul>', wp_terms_checklist( get_the_ID(), 'taxonomy=my_taxonomy&checked_ontop=0'), '</ul>';

タームの並び順を好きな順番に変更する

記事毎にタームの並び順を指定する」 term_order という情報が wp_term_relationships テーブルにあります。register_taxonomy() のオプションに 'sort' => true を指定しておいて wp_set_object_terms()順序付けしたターム(の ID またはスラッグ)配列を渡すと term_order が設定され、wp_get_object_terms() のオプションに 'orderby' => 'term_order' を指定すると指定した順序でタームを取得できます。

register_taxonomy( 'my_taxonomy', 'my_post_type', array(
  'sort' => true,
    :
);

$terms_to_set = array( 'orange', 'melon', 'apple' );
wp_set_object_terms( $post->ID, $terms_to_set, 'my_taxonomy' );
  :

$terms = wp_get_object_terms( $post->ID, 'my_taxonomy', array(
  'orderby' => 'term_order',
  'fields' => 'names',
) );

でもこれは記事毎の並び順なので使いづらいですね。

並び順の指定にプラグインを使う

よく利用されるプラグインは以下の2つでしょうか。

Category Order and Taxonomy Terms Order は階層ありのタクソノミーのみが対象ですね、何故… いずれのプラグインも下記の私的な要望には合わないため、自作することにしました。

  • wp_terms テーブルに order 用のカラムを追加したくない。
  • 並び順の指定は専用ページではなく、ビルトインの一覧画面でドラッグ&ドロップしたい。

並び順を変更するプラグインを作った

Anything Order というプラグインを作成して、Plugin Directory に登録してみました。詳しくは Anything Order の公式プラグインディレクトリ をご覧ください。Anything なのでタクソノミーだけでなく、各種投稿タイプの並び順変更にも使えます。

特長
  • 以下の関数で並び順が指定した通りになります。
  • 前項の関数で orderby の指定は不要です。指定がある場合は、並び順 → orderby指定 の順になります。
  • 複数の項目をドラッグ&ドロップして並び替えできます。
  • 並び順をリセット(クリア)できます。
  • 特定のタクソノミーで並び替えしたくない場合は「表示オプション」でカラムを非表示にします。
  • 並び替えをするには以下の権限が必要です。
    • 投稿タイプ:’edit_others_posts’
    • タクソノミー:’manage_terms’
  • プラグイン専用の設定ページはありません。
  • ビルトインのテーブル構造を変更しません。
今後の予定
  • ドラッグ&ドロップで親子関係を変更したい。
  • Anything なのでユーザー等(等?)の並び順も変更したいかもしれない。

ご要望・バグレポートをお待ちしてます!