WordPress の管理画面でターム一覧をカスタマイズする方法

WordPress の管理画面カスタマイズで投稿やカスタム投稿タイプに関しては参考記事が多くありますが、ターム一覧画面のカスタマイズ情報が少なかったのでまとめました。
特に、ターム一覧の絞り込み機能を追加する機能は必見です。

前提条件

  • 検証した WordPress のバージョンは 5.7.1
  • 使用するタームは投稿のカテゴリーです。
  • Advanced Custom Fields PRO を使用してタームに入力欄を追加しています。
    追加した項目を絞り込み対象にしています。
    例として「認証(Authentication)」というカスタムフィールドを設定していて、Selectで「OK(ok)」「NG(ng)」「未認証(unconfirmed)」という値を選択できるようにしています。

ターム一覧に列を追加

function add_taxonomy_category_columns($columns)
{
    $column_slug = $columns['slug'];
    $column_posts = $columns['posts'];

    unset($columns['slug']);
    unset($columns['posts']);

    $columns['authentication'] = __('Authentication');
    $columns['slug'] = $column_slug;
    $columns['posts'] = $column_posts;

    return $columns;
}
add_filter('manage_edit-category_columns', 'add_taxonomy_category_columns');

function custom_taxonomy_category_column($content, $column_name, $term_id)
{
    if ($column_name == 'authentication') {
        $authentication = get_term_meta($term_id, 'authentication', true);

        switch ($authentication) {
            case 'ok':
                echo '<span class="fc-ok">'. __('OK'). '</span>';
                break;
            case 'ng':
                echo '<span class="fc-ng">'. __('NG'). '</span>';
                break;
            case 'unconfirmed':
            default:
                echo '<span class="fc-unconfirmed">'. __('unconfirmed'). '</span>';
        }
    }
}
add_action('manage_category_custom_column', 'custom_taxonomy_category_column', 10, 3);

add_taxonomy_category_columns

こちらの関数で一覧の列の見出しを設定します。$columns['slug'] $columns['posts'] をunsetしているのは列の順番を変更するためです。

add_filter('manage_edit-category_columns', 'add_taxonomy_category_columns');

こちらのフィルターを使用する場合は「manage_edit-category_columns」の部分が「manage_edit-{タームのスラッグ}_columns」となります。

投稿のタグに設定する場合は「manage_edit-post_tag_columns」となります。

custom_taxonomy_category_column

この関数ではターム一覧の各行に表示される内容を指定します。カスタムフィールドに入っている内容によって表示の振り分けを行っています。

add_action('manage_category_custom_column', 'custom_taxonomy_category_column', 10, 3);

こちらのフィルターを使用する場合は「manage_category_custom_column」の部分が「manage_{タームのスラッグ}_custom_column」となります。

投稿のタグに設定する場合は「manage_post_tag_custom_column」となります。

ターム一覧上部に絞り込みを追加

function views_edit_category($views)
{
    $post_type = 'post';
    $taxonomy = 'category';
    
    $types = array(
        array('authentication' => NULL),
        array('authentication' => 'ok'),
        array('authentication' => 'ng'),
        array('authentication' => 'unconfirmed')
    );

    remove_filter('pre_get_terms', 'pre_get_terms_edit_category');
    
    foreach ($types as $type) {

        $query = array(
            // タクソノミー(カスタム分類)を指定
            'taxonomy' => array($taxonomy),
            // 投稿のないターム(カスタム分類のカテゴリ)も取得
            'hide_empty' => false,
            'fields' => 'count',
        );
        if ($type['authentication']) {
            $query['meta_query'] = array(
                array(
                    'key' => 'authentication',
                    'value' => $type['authentication'],
                )
            );
        }
        
        
        $result = get_terms($query);
        
        if ($type['authentication'] == NULL):
            $class = (empty($_GET['authentication'])) ? ' class="current"' : '';
            $views['all'] = sprintf(__('<a href="%s"' . $class . '>' . __('All') . ' <span class="count">(%d)</span></a>', 'all'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type),
                $result);
        elseif ($type['authentication'] == 'ok'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'ok') ? ' class="current"' : '';
            $views['ok'] = sprintf(__('<a href="%s"' . $class . '>' . __('OK') . ' <span class="count">(%d)</span></a>', 'publish'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        elseif ($type['authentication'] == 'ng'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'ng') ? ' class="current"' : '';
            $views['ng'] = sprintf(__('<a href="%s"' . $class . '>' . __('NG') . ((sizeof($result) > 1) ? "s" : "") . ' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        elseif ($type['authentication'] == 'unconfirmed'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'unconfirmed') ? ' class="current"' : '';
            $views['unconfirmed'] = sprintf(__('<a href="%s"' . $class . '>' . __('unconfirmed') . ' <span class="count">(%d)</span></a>', 'pending'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        endif;
    }

    add_filter('pre_get_terms', 'pre_get_terms_edit_category');
    
    return $views;
}
add_filter('views_edit-category', 'views_edit_category');

function pre_get_terms_edit_category($query)
{
    if(is_admin() && (!get_current_screen() || get_current_screen()->id != 'edit-tag')) {
        return;
    }
    
    if ($_GET['authentication']) {
        $meta_query = array(
            array(
                'key' => 'authentication',
                'value' => $_GET['authentication'],
            )
        );
        $query->query_vars['meta_query'] = $meta_query;
    }
}
add_filter('pre_get_terms',  'pre_get_terms_edit_category');

views_edit_category($views)

こちらの関数でターム一覧上部の絞り込みを表示します。
ポイントは remove_filter('pre_get_terms', 'pre_get_terms_edit_category');add_filter('pre_get_terms', 'pre_get_terms_edit_category'); です。
処理を行う前に後述のフィルターを一度削除し、最後に追加します。
このフィルターはmain_queryに影響を与えるので処理の邪魔になるためです。

add_filter('views_edit-category', 'views_edit_category');

こちらのフィルターを使用する場合は「views_edit-category」の部分が「views_edit-{タームのスラッグ}」となります。

投稿のタグに設定する場合は「views_edit-post_tag」となります。

pre_get_terms_edit_category($query)

こちらの関数でターム一覧に絞り込む処理を行います。
絞り込みに使用するパラメータが存在する場合、$query->query_vars['meta_query'] に絞り込み条件を追加します。

add_filter('pre_get_terms', 'pre_get_terms_edit_category');

こちらのフィルターはターム一覧を取得する前に処理を割り込ませます。その際に絞り込み条件を設定します。

参考サイト

manage_{$screen->id}_columns | Hook | WordPress Developer Resources
Filters the column headers for a list table on a specific screen.
manage_{$this->screen->taxonomy}_custom_column | Hook | WordPress Developer Resources
Filters the displayed columns in the terms list table.
views_{$this->screen->id} | Hook | WordPress Developer Resources
Filters the list of available list table views.
pre_get_terms | Hook | WordPress Developer Resources
Fires before terms are retrieved.