巷でWordPressの投稿に紐づけるカテゴリーの選択をラジオボタンにするコードは結構紹介されており、以下のようなものが多いです。
- ブロックエディターのカテゴリーパネルに無理やり割り込んで改変しようとするもの
- 旧エディター(クラシックエディター)用で、ブロックエディターのカテゴリーパネルには何も作用しないもの
私も結構そのようなコードを試したのですが、どれもうまくいかず、以下の仕様のようなちょっと変わったアプローチで実装したところうまくいきましたので、同じような機能を求めている方のため、自身の備忘録として公開しておきます。
投稿編集画面のカテゴリー選択を一択(ラジオボタン)にするコードの仕様
本ページで紹介するコードは以下のような仕組みになっています。
- ラジオボタン化したカスタムフィールド入力ボックスを表示
- 入力ボックスにはカテゴリーから取得した情報を表示
- 「下書き保存」「保存」「公開」を行った際に、カスタムフィールドの値を保存し、同時にカテゴリーへ反映させる
つまり、単純にカテゴリーの選択項目をラジオボタンに単に変更するものではなく、新たにカテゴリーから引いてきたID・名称を元にカスタムフィールドの入力ボックスを作り、カスタムフィールドの値を保存した後に同時に元のカテゴリーへデータを戻すということをしています。
これによって以下のことについては残念ながら実現できませんので、それでもよければ基本的にコピペで実装できますので使ってみてください。
- 本来のカテゴリー欄ではないため、編集画面のサイドバー内で少なくともWordPress標準の設定パネル(恐らく「タグ」が一番下かと思われます)より上には配置できない
- 標準のカテゴリー選択パネルにある「検索」と「カテゴリーの追加」機能は使えない
- クイック編集ではセレクトボックス(複数選択可能)のままになる。(コードではセレクトボックス上に注意文章を表示させることはしています)
なぜこんな仕様にする必要があるかについては文末の「WordPress標準パネルを直接カスタマイズするのは難しい」をご覧ください。
多分この機能を実装したいという方は、他者が投稿する際のカテゴリー選択を制限したいという主旨で追加しようとする方だと思うので、上記の2についてはそもそも不要なのではないかと思います
ここまで読んで、やっぱりどうしても標準パネルを直接カスタマイズしたいと考える方は素直に以下のプラグインを利用することをおすすめします。
投稿編集画面でカテゴリー選択を一択にするコード
コードは以下の流れで構成しています。
- 仮のカテゴリーを格納する(カスタムフィールドとして格納する)メタボックスと内容を追加する
- メタボックスの内容を保存すると同時に、カテゴリーのデータへ反映させる
- WordPress標準のカテゴリー選択パネルを非表示にする
- クイック編集画面のカテゴリー選択項目上部へ注意文章を表示する
以後、順にコードと簡易説明をしていきます。
仮のカテゴリーを格納するメタボックスと内容を追加する
以下のコードで仮(カスタムフィールドに一旦保存する)カテゴリーを選択するための設定窓と内容を追加します。
/*** ラジオボタンで仮のカテゴリーを選択するためカスタムメタボックスを追加 ***/
function pwcn_add_temp_category_metabox(){
$title = 'カテゴリー';
add_meta_box(
'temp_category_selection',// メタボックスのID
$title,// メタボックスのタイトル
'pwcn_render_temp_category_metabox', // コールバック関数
'post',// 投稿タイプ
'side',// 表示場所
'high'// 優先度
);
}
add_action( 'add_meta_boxes', 'pwcn_add_temp_category_metabox' );
/*** メタボックスに表示する内容のコールバック関数 ***/
function pwcn_render_temp_category_metabox( $post ) {
// 1. カスタムフィールドから現在の保存値を取得
$current_id = get_post_meta( $post->ID, '_temp_category_id', true );
// 2. カスタムフィールドが空、または投稿が新規ではない場合
if ( empty( $current_id ) && $post->post_status !== 'auto-draft' ) {
// 投稿に現在設定されているカテゴリーIDの配列を取得
$terms = wp_get_post_terms( $post->ID, 'category', array( 'fields' => 'ids' ) );
if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
// 複数ある場合、最初のカテゴリーを現在のIDとする (単一選択のため)
$current_id = absint( $terms[0] );
}
}
// 既存のget_post_metaから取得した値、またはwp_get_post_termsから取得した値を使用
$current_id = absint( $current_id );
// nonceフィールドの追加(セキュリティ対策)
wp_nonce_field( 'temp_category_save', 'temp_category_nonce' );
// 既存カテゴリーのリストを取得
$categories = get_terms( array(
'taxonomy' => 'category',
'hide_empty' => false,
'parent' => 0, // 最上位のカテゴリーのみを取得
'orderby' => 'name',
));
// スタイル調整用のCSSをインラインで追加
echo '<style>.category-radio-list li { margin-bottom: 3px; }</style>';
if ( ! empty( $categories ) && ! is_wp_error( $categories ) ) {
echo '<ul class="category-radio-list" style="list-style: none; margin-left: 0;">';
// 階層表示関数pwcn_display_category_radio_hierarchy()を呼び出す
foreach ( $categories as $category ) {
pwcn_display_category_radio_hierarchy( $category, $current_id );
}
echo '</ul>';
}
}
/*** カテゴリーを階層的に表示するための再帰関数 */
/* @param object $term 現在処理中のタームオブジェクト */
/* @param int $current_id 現在選択されているタームID */
/* @param int $depth タームの深さ (0から開始) */
function pwcn_display_category_radio_hierarchy( $term, $current_id, $depth = 0 ) {
// インデント用のスペース
$indent = str_repeat( '— ', $depth );
// ラジオボタンの出力 (valueはタームID)
$checked = checked( $current_id, $term->term_id, false );
echo '<li>';
echo '<label style="display: block; padding-left: ' . ( $depth * 15 ) . 'px;">';
echo '<input type="radio" name="temp_category_radio" value="' . esc_attr( $term->term_id ) . '" ' . $checked . '/> ';
echo $indent . esc_html( $term->name );
echo '</label>';
echo '</li>';
// 子タームを取得し、関数自身を呼び出し(再帰)
$children = get_terms( array(
'taxonomy' => 'category',
'hide_empty' => false,
'parent' => $term->term_id,
'orderby' => 'name',
));
if ( ! empty( $children ) && ! is_wp_error( $children ) ) {
foreach ( $children as $child_term ) {
pwcn_display_category_radio_hierarchy( $child_term, $current_id, $depth + 1 );
}
}
}
コード追加後、何かの投稿の編集画面を開くと、サイドパネルの最下部に以下のようなラジオボタン式のパネルが追加されているはずですので確認しましょう(画像は私のテストサイトのもので、実際にはあなたのサイトのカテゴリーが階層で表示され、ラジオボタンで選択が可能になっているはずです)。

メタボックスの内容を保存すると同時に、カテゴリーのデータへ反映させる
前項のコードでは、メタボックスにカテゴリーの選択肢が表示されるだけで投稿を保存しても何も反映されません。
以下のコードを使って、投稿の「下書き保存」「保存」「公開」ボタンをクリックした時に、カスタムフィールドに値を保存するのと同時にカテゴリーへデータを反映させる(返す)ようにします。
/*** メタボックスの値を保存し、標準カテゴリーに反映させる ***/
function pwcn_save_temp_category_data( $post_id ) {
// 紐づかなかった場合のデフォルトカテゴリーID
$default_category_id = absint(get_option('default_category'));
// nonceチェック
if ( ! isset( $_POST['temp_category_nonce'] ) || ! wp_verify_nonce( $_POST['temp_category_nonce'], 'temp_category_save' ) ) {
return $post_id;
}
//自動保存では実行しない
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
//投稿編集権限がない場合は実行しない
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
// ラジオボタンから送信されたIDを取得
$submitted_id = isset( $_POST['temp_category_radio'] ) ? absint($_POST['temp_category_radio']) : 0;
$custom_field_key = '_temp_category_id';
/* タームIDの有効性チェックとフォールバック処理 */
$term_id_to_save = $submitted_id;
// 選択されたIDが0(未選択)、または有効なタームIDではない場合
if ( $submitted_id === 0 || ! term_exists( $submitted_id, 'category' ) ) {
// 紐づけが解除された(未選択または削除された)とみなし、デフォルトIDに設定
$term_id_to_save = $default_category_id;
//未選択の場合はカスタムフィールドもデフォルトIDで更新する
update_post_meta( $post_id, $custom_field_key, $term_id_to_save );
} else {
// 選択されたIDが有効な場合、カスタムフィールドをそのIDで更新
update_post_meta( $post_id, $custom_field_key, $term_id_to_save );
}
/* カスタムフィールドの値を元に標準カテゴリーへ反映 */
// 有効なタームID(またはデフォルトID)を割り当てる
wp_set_post_terms(
$post_id,
array( $term_id_to_save ),
'category',
false // 既存のカテゴリーを全て上書き
);
return $post_id;
}
add_action( 'save_post', 'pwcn_save_temp_category_data' );
コードを追加したら、投稿編集画面を開き(既に開いている場合には画面をリロードして)、何かのカテゴリーを選択しなおして保存してみてください。
再度画面をリロードすると、今まで使っていたカテゴリーパネル(複数選択が可能になっているパネル)側も、選択しなおしたカテゴリーにのみチェックが入っているはずです
WordPress標準のカテゴリー選択パネルを非表示にする
ここまでのコードでは、ラジオボタン式のパネルと、従来のセレクトボックス(複数選択)のパネルが共存してしまっていますので、以下のコードを追加して従来側のパネルを非表示にします。
/*** Gutenbergの編集画面から標準カテゴリーUIを非表示にする ***/
function pwcn_disable_default_category_ui() {
$taxonomy = get_taxonomy( 'category' );
if ( $taxonomy ) {
// show_in_rest を false に設定すると、Gutenbergのサイドバーパネルから削除されます
$taxonomy->show_in_rest = false;
// メタボックスとしても表示させないように
$taxonomy->meta_box_cb = false;
}
}
add_action( 'init', 'pwcn_disable_default_category_ui', 100 );
追加したら投稿編集画面を開きなおす、またはリロードして、従来のカテゴリーパネルが表示されていないことを確認してください
クイック編集画面のカテゴリー選択項目上部へ注意文章を表示する
冒頭でも書いた通り、本ページのコードではクイック編集画面のラジオボタン化には対応していませんので、以下のコードを追加して、ボックスの上部に注意書きを表示させるようにします。
/*** クイック編集に注意書きを追加するJavaScriptを管理画面に出力 ***/
function pwcn_add_quick_edit_single_category_note() {
// 管理画面でのみ実行
if ( ! is_admin() ) {
return;
}
$notice_text = '1つの投稿を複数のカテゴリーに紐づけることはSEOにマイナスとなることがため、1つのみ選択することをおすすめします';
?>
<script type="text/javascript">
// IIFE (即時実行関数式) を利用し、グローバルスコープを汚染しない
(function($) {
if (typeof $ === 'undefined') {
return;
}
function addQuickEditCategoryNote() {
// 投稿一覧テーブル全体を監視
$('#the-list').on('click', '.editinline', function() {
// パネルのDOMがロードされるのを待つために遅延
setTimeout(function() {
const $categoryChecklist = $('.inline-edit-row .category-checklist');
// 既に注釈が挿入されているかチェック
if ($categoryChecklist.length && $categoryChecklist.prev('.category-limit-note').length === 0) {
const noteHtml = `<p class="pwcn-category-limit-note" style="background-color: #f4ffe6; border: 1px solid #67b00b; padding: 8px;margin: 0 0 10px 0;font-size: 0.8rem;color: #555;font-weight:500;"><?php echo $notice_text; ?></p>`;
$categoryChecklist.before(noteHtml);
}
}, 50);
});
}
// DOMContentLoaded相当のイベントで関数を実行
$(document).ready(function() {
addQuickEditCategoryNote();
});
})(jQuery);
</script>
<?php
}
add_action('admin_head', 'pwcn_add_quick_edit_single_category_note');
以上で、投稿編集画面のカテゴリー選択を一択(ラジオボタン)にするコードの仕様で書いた通りの機能を実装できました。
コードの内容については細かく解説しないので、ご自身で解読ください。
WordPress標準パネルを直接カスタマイズするのは難しい
本ページのコード作成に当たっては、自身でコードを書きながら、AIに手伝ってもらって完成させました。
当初は何とかWordPress標準のカテゴリーパネルに直接的なカスタマイズを試みましたが、ラジオボタン化するまでは実装できたものの、肝心の更新時にどうしても反映できないという結論に至りました。
そこで考えたのが、今回紹介したカスタムフィールドを使用する方法で、この方法であれば紹介したコードのようにWordPress標準の関数やフックで反映させることができたため、この仕様にして公開することにしました。
また、カスタムフィールドやメタボックスについてはWordPressの中でも超標準的な機能であり、まだまだ発展途上のブロックエディター(Gutenberg)のように仕様が変わる恐れが少ないと考えたのも、この仕様で決着した理由の1つです。
冒頭で紹介した「Radio Buttons for Taxonomies」も、ざっとコードを見る限りでは同じような仕組みをしているようなのですが、通常のカテゴリーパネルやクイック編集画面に割り込んできちんと処理されるようになっており、本ページのコードと比べたら雲泥の差と言える完成度ですし、恐らくブロックエディターの仕様が変わったら都度対応されていくと思いますので、どうしてもコードで..ということでなければプラグインを使った方がいいと私自身も思います。










コメントを残す