サイドバーに「カテゴリーで絞り込む」プルダウンを置きたい、記事の投稿画面や検索フォームでカテゴリーを <select> から選ばせたい——そんなときに便利なのが wp_dropdown_categories() です。カテゴリーを <option> に展開した <select> を、引数の指定だけで組み立ててくれます。この記事では、wp_dropdown_categories() の基本的な使い方から、よく使う引数の意味、echo を false にしてHTML文字列として受け取る方法、選んだカテゴリーのページへ移動させる実装、カスタムタクソノミーでの使い方までを、実際に動くコードで解説します。
目次
wp_dropdown_categories で何ができるか
wp_dropdown_categories() は、サイトに登録されているカテゴリーを <option> に展開し、それらを含む <select> 要素を出力するテンプレートタグです。各 <option> の value にはカテゴリーのID(term_id)が入り、表示テキストにはカテゴリー名が入ります。投稿数の表示、空カテゴリーの除外、並び順の指定、親子階層の入れ子表現なども、すべて引数で切り替えられます。
ここで注意したいのは、この関数が出力するのは <select> 単体だけという点です。<select> を選んでも何かが起きるわけではありません。「選んだカテゴリーのページへ移動する」といった動きは、JavaScript やフォーム送信を自分で組み合わせて実現します。これについては後半で具体的に説明します。
基本の使い方
もっとも単純な使い方は、引数なしで wp_dropdown_categories() を呼び出すことです。次の例はサイドバー用テンプレート sidebar.php での記述です。
<?php wp_dropdown_categories(); ?>
これだけで、次のような <select> が出力されます。各 <option> の value にはカテゴリーのIDが入っている点に注目してください。
<select name="cat" id="cat" class="postform">
<option class="level-0" value="3">お知らせ</option>
<option class="level-0" value="5">ブログ</option>
</select>
デフォルトでは name と id がどちらも cat になり、class に postform が付きます。親子関係のあるカテゴリーは、子カテゴリー名の前に空白(インデント)が付いた <option> として、階層が分かるように出力されます。
よく使う引数
wp_dropdown_categories() は、引数に連想配列を渡すことで出力を細かく調整できます。よく使う引数と、その意味・既定値を次の表にまとめました。
| 引数 | 既定値 | 説明 |
|---|---|---|
show_option_all | '' | 先頭に「すべて」を表す <option>(value は空)を追加する。渡した文字列がその表示テキストになる |
show_option_none | '' | 「選択なし」を表す <option> を追加する。value は次の option_none_value の値になる |
option_none_value | -1 | show_option_none の <option> の value |
orderby | 'id' | 並び替えの基準。name(名前)・id・count(投稿数)・slug など |
order | 'ASC' | 並び順。ASC(昇順)または DESC(降順) |
show_count | 0(false) | 1 にすると各カテゴリー名の後ろに投稿数を表示する |
hide_empty | 1(true) | 1 なら投稿が0件のカテゴリーを除外。0 で空のカテゴリーも表示する |
hierarchical | 0(false) | 1 にすると親子をインデント付きの入れ子で表現する |
depth | 0 | 表示する階層の深さ。0 は無制限。hierarchical と組み合わせて使う |
name | 'cat' | 出力する <select> の name 属性 |
id | name と同じ | 出力する <select> の id 属性 |
selected | 0 | 初期選択にするカテゴリーの値(既定では term_id) |
taxonomy | 'category' | 対象のタクソノミー。カスタムタクソノミーを使うときに指定する |
value_field | 'term_id' | <option> の value に使うフィールド。slug なども指定できる |
echo | 1(true) | 1 ならその場で出力。0(false)にすると出力せずHTML文字列を返す |
次の例は、先頭に「すべてのカテゴリー」を追加し、名前の昇順で並べ、投稿数も表示する指定です。
<?php
wp_dropdown_categories( array(
'show_option_all' => 'すべてのカテゴリー', // 先頭に「すべて」を追加
'orderby' => 'name', // 名前を基準に並べる
'order' => 'ASC', // 昇順
'show_count' => 1, // 投稿数を表示
'hierarchical' => 1, // 親子を入れ子で表現
) );
?>
show_option_all に文字列を渡すと、value が空の <option> が先頭に追加され、その文字列が表示テキストになります。orderby の既定値は id なので、名前順に並べたいときは明示的に name を指定します。
echo を false にして文字列で受け取る
標準では wp_dropdown_categories() はその場で <select> を出力(echo)しますが、echo 引数を false(または 0)にすると、出力せずにHTML文字列を返します。出力前に加工したい場合や、変数に入れてラベルと一緒に組み立てたい場合に便利です。
<?php
// echo を false にすると、出力せずに <select> の文字列が返る
$dropdown = wp_dropdown_categories( array(
'show_option_all' => 'カテゴリーを選択',
'echo' => false,
) );
// ラベルと一緒に自分で組み立てて出力する
echo '<label for="cat">カテゴリーで絞り込む</label>';
echo $dropdown;
?>
返ってくるのは <select>...</select> の文字列一式です。<label> の for は、出力される <select> の id(既定では cat)に合わせておくと、ラベルとフォーム部品が正しく関連付きます。
選んだカテゴリーのページへ移動させる
wp_dropdown_categories() が出力するのは <select> だけなので、そのままでは選んでも何も起きません。「選んだカテゴリーのアーカイブページへ移動する」動きを付けるには、大きく2つの方法があります。JavaScript の onchange で遷移させる方法と、フォーム送信を使う方法です。
JavaScript の onchange で移動する
選択したときに、その <option> の value(=カテゴリーID)から作ったURLへ移動させる方法です。カテゴリーIDから移動先URLを組み立てるには、WordPress の get_category_link() を使うのが確実です。value_field は既定の term_id のまま使います。
<?php
// onchange で、選んだ option の value(カテゴリーID)を関数に渡す
wp_dropdown_categories( array(
'show_option_none' => 'カテゴリーを選択',
'option_none_value' => '-1',
'id' => 'cat-select',
) );
?>
<script>
document.getElementById( 'cat-select' ).addEventListener( 'change', function () {
var termId = this.value;
// 「選択なし」(-1) のときは何もしない
if ( termId === '-1' || termId === '' ) {
return;
}
// 各 option に data-url を持たせている場合はそれを使う(後述)
var url = this.options[ this.selectedIndex ].dataset.url;
if ( url ) {
window.location.href = url;
}
} );
</script>
上の JavaScript は各 <option> に移動先URLを持たせておく前提です。wp_dropdown_categories() の標準の <option> には value(ID)しか入らないため、ID からURLへ変換する手段が必要になります。手軽なのは、PHP 側でカテゴリーを取得して <select> を自作し、各 <option> の value に get_category_link() のURLを入れてしまう方法です。
<select id="cat-jump">
<option value="">カテゴリーを選択</option>
<?php foreach ( get_categories() as $cat ) : ?>
<option value="<?php echo esc_url( get_category_link( $cat->term_id ) ); ?>">
<?php echo esc_html( $cat->name ); ?>
</option>
<?php endforeach; ?>
</select>
<script>
// option の value にURLそのものを入れてあるので、そのまま遷移できる
document.getElementById( 'cat-jump' ).addEventListener( 'change', function () {
if ( this.value ) {
window.location.href = this.value;
}
} );
</script>
この書き方なら、<option> の value にカテゴリーページのURLが直接入るため、JavaScript 側は this.value をそのまま window.location.href に渡すだけで済みます。esc_url() と esc_html() で出力をエスケープしている点も、テーマを書くうえで大切な作法です。
フォーム送信を使う
JavaScript を使わず、フォーム送信でカテゴリーアーカイブに飛ばす方法もあります。wp_dropdown_categories() の <select> は name が既定で cat です。WordPress はクエリ変数 cat にカテゴリーIDを受け取ると、そのカテゴリーの一覧を表示します。そこで、フォームの送信先をサイトのトップURLにしておけば、選んだIDが ?cat=5 のように付いて、該当カテゴリーの表示に切り替わります。
<form action="<?php echo esc_url( home_url( '/' ) ); ?>" method="get">
<label for="cat">カテゴリーで絞り込む</label>
<?php
// name は既定の cat のまま。cat はカテゴリー絞り込み用のクエリ変数
wp_dropdown_categories( array(
'show_option_none' => '選択してください',
'option_none_value' => '-1',
) );
?>
<button type="submit">表示</button>
</form>
この方法は JavaScript を必要とせず、送信ボタンを押すと ?cat=(ID) 付きでトップURLに GET 送信され、WordPress がそのカテゴリーのアーカイブを表示します。送信ボタンを置かずに onchange でフォームを自動送信したい場合は、<form> にIDを付けて、選択時に form.submit() を呼ぶとよいでしょう。
value_field を slug にする
value_field を 'slug' にすると、<option> の value にカテゴリーIDではなくスラッグ(英字のカテゴリー名)が入ります。IDよりも意味の分かる値をフォームで扱いたいときや、URLの一部にスラッグを使いたいときに便利です。
<?php
wp_dropdown_categories( array(
'value_field' => 'slug', // option の value をスラッグにする
) );
?>
出力される <option> は <option value="blog">ブログ</option> のようになります。ただし、フォーム送信で標準のカテゴリー絞り込み(name="cat")を使う場合、クエリ変数 cat はIDを前提とするため、スラッグを value にすると噛み合いません。value_field にスラッグを使うときは、送信先や受け取り側の処理もスラッグを前提に組み立てる必要があります。
カスタムタクソノミーで使う
wp_dropdown_categories() という名前ですが、taxonomy 引数を指定すれば、投稿カテゴリー以外のタクソノミー(独自に登録した分類)でも同じ形式のプルダウンを出力できます。たとえば product_cat という階層型カスタムタクソノミーがある場合は、次のように書きます。
<?php
wp_dropdown_categories( array(
'taxonomy' => 'product_cat', // 対象のタクソノミー
'show_option_all' => 'すべての商品カテゴリー',
'hierarchical' => 1,
'name' => 'product_cat', // 標準の cat と分けておく
) );
?>
対象をカテゴリーからカスタムタクソノミーに切り替えるだけで、投稿数表示や並び替えといった他の引数はそのまま使えます。なお name を cat のままにすると投稿カテゴリー用のクエリ変数とぶつかることがあるため、カスタムタクソノミーではタクソノミー名などに合わせて name を変えておくと安全です。
選んでも移動しない・value に何が入るか
この関数まわりでつまずきやすいのは、出力される <select> の性質を誤解しているケースがほとんどです。よくある2点を整理します。
選択しても何も起きない
wp_dropdown_categories() が出力するのは <select> だけで、遷移や送信のしくみは含まれていません。プルダウンを選んでもページが変わらないのは正常な動作です。移動させたい場合は、前述のように onchange の JavaScript で遷移させるか、<form> で囲ってフォーム送信するかを、自分で用意する必要があります。「関数を呼べば絞り込みまで動く」わけではない、と押さえておきましょう。
option の value にはIDが入っている
既定では <option> の value はカテゴリーのURLではなく、カテゴリーID(term_id)です。そのため、value をそのまま window.location.href に渡してもページには飛べません。value のIDから移動先URLを作るには get_category_link() を通す必要があります。IDの変換をはさむのが面倒なら、この記事で示したように <option> の value にURLそのものを入れる形で <select> を自作するのも実用的な選択肢です。
プルダウンが空になる
選択肢が出てこないときは、hide_empty の既定値が 1 であることを疑ってください。投稿が割り当てられていないカテゴリーは、既定では <option> に出てきません。テスト中でまだ投稿がない場合や、意図的に空カテゴリーも出したい場合は、'hide_empty' => 0 を指定すると表示されるようになります。
まとめ
wp_dropdown_categories() は、カテゴリーの <select> プルダウンを引数の指定だけで手軽に作れるテンプレートタグです。要点を振り返ります。
- 出力されるのは
<select>単体で、<option>の value には既定でカテゴリーID(term_id)が入る show_option_all/show_option_noneで先頭に選択肢を足せるorderbyの既定はid。名前順にしたいならnameを明示するecho => falseで出力せずHTML文字列として受け取れる- 選択で移動させるには
onchangeの JavaScript か<form>送信を自分で用意する taxonomyでカスタムタクソノミーにも使え、value_fieldで value をスラッグに変えられる
「関数はプルダウンを出すだけ」「移動のしくみは別で用意する」という役割分担を理解すれば、絞り込みメニューやカスタムタクソノミーの選択UIまで、無理なく作れるようになります。