WordPress のカテゴリーに背景色・文字色を持たせて、色つきのボタンで出す(タームメタ・nonce・色のチェックつき)

広告WordPress・PHP を学べる本

Amazonのアソシエイトとして、WordPress functions.phpは適格販売により収入を得ています。

概要説明

カテゴリーの編集画面に背景色と文字色の欄を足し、記事のカテゴリーを色つきのボタンで出すコード。前のコードは PHP 8 の警告、色の欄の値がそのまま HTML に入る、クイック編集で色が消える問題があったので、タームメタと nonce、色のチェックで書き直し、作業環境で確かめました。

WordPress のカテゴリーに背景色・文字色を持たせて、色つきのボタンで出す(タームメタ・nonce・色のチェックつき)

管理画面のカテゴリーの画面で色を決められるようにすると、カテゴリーを足したときも、CSS を書き足さずに色を付けられます。

この記事のコードでは、色はカテゴリーごとの「タームメタ」に保存します。色のコード(#ff0000 など)でない値は保存しません。

カテゴリーの画面に、背景色・文字色の欄を足す

functions.php
/*----------------------------------------------------
 カテゴリーに背景色・文字色を持たせる(タームメタ)
----------------------------------------------------*/

// 1. 保存する値の決まり(色のコードだけを受け付ける)
function fs_cat_color_register_meta() {
	foreach ( array( 'cat_color_bg', 'cat_color_txt' ) as $key ) {
		register_term_meta( 'category', $key, array(
			'type'              => 'string',
			'single'            => true,
			'sanitize_callback' => 'sanitize_hex_color',
			'show_in_rest'      => true,
		) );
	}
}
add_action( 'init', 'fs_cat_color_register_meta' );

// 2. 入力欄(新規追加の画面)
function fs_cat_color_add_fields() {
	wp_nonce_field( 'fs_cat_color_save', 'fs_cat_color_nonce' );
	?>
	<div class="form-field">
		<label for="cat_color_bg">カテゴリー背景色</label>
		<input type="text" name="cat_color_bg" id="cat_color_bg" value="" class="fs-color-field" placeholder="#1e73be">
	</div>
	<div class="form-field">
		<label for="cat_color_txt">カテゴリー文字色</label>
		<input type="text" name="cat_color_txt" id="cat_color_txt" value="" class="fs-color-field" placeholder="#ffffff">
	</div>
	<?php
}
add_action( 'category_add_form_fields', 'fs_cat_color_add_fields' );

// 3. 入力欄(編集の画面)
function fs_cat_color_edit_fields( $term ) {
	$colors = fs_get_category_colors( $term->term_id );
	wp_nonce_field( 'fs_cat_color_save', 'fs_cat_color_nonce' );
	?>
	<tr class="form-field">
		<th scope="row"><label for="cat_color_bg">カテゴリー背景色</label></th>
		<td><input type="text" name="cat_color_bg" id="cat_color_bg" value="<?php echo esc_attr( $colors['bg'] ); ?>" class="fs-color-field"></td>
	</tr>
	<tr class="form-field">
		<th scope="row"><label for="cat_color_txt">カテゴリー文字色</label></th>
		<td><input type="text" name="cat_color_txt" id="cat_color_txt" value="<?php echo esc_attr( $colors['txt'] ); ?>" class="fs-color-field"></td>
	</tr>
	<?php
}
add_action( 'category_edit_form_fields', 'fs_cat_color_edit_fields' );

// 4. 保存(自分の入力欄が送られたときだけ)
function fs_cat_color_save( $term_id ) {
	if ( ! isset( $_POST['fs_cat_color_nonce'] )
		|| ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['fs_cat_color_nonce'] ) ), 'fs_cat_color_save' ) ) {
		return; // クイック編集や、ほかの処理から呼ばれたときは何もしない
	}
	if ( ! current_user_can( 'edit_term', $term_id ) ) {
		return;
	}
	foreach ( array( 'cat_color_bg', 'cat_color_txt' ) as $key ) {
		$color = isset( $_POST[ $key ] ) ? sanitize_hex_color( wp_unslash( $_POST[ $key ] ) ) : '';
		update_term_meta( $term_id, $key, (string) $color ); // 色でない値は空になる
	}
}
add_action( 'created_category', 'fs_cat_color_save' );
add_action( 'edited_category', 'fs_cat_color_save' );

// 5. 管理画面でカラーピッカーを使う
function fs_cat_color_admin_scripts( $hook ) {
	if ( ! in_array( $hook, array( 'edit-tags.php', 'term.php' ), true ) ) {
		return;
	}
	wp_enqueue_style( 'wp-color-picker' );
	wp_enqueue_script( 'wp-color-picker' );
	wp_add_inline_script( 'wp-color-picker', 'jQuery(function($){ $(".fs-color-field").wpColorPicker(); });' );
}
add_action( 'admin_enqueue_scripts', 'fs_cat_color_admin_scripts' );

// 6. 色を取り出す(前の書き方で保存した cat_{id} のオプションも読む)
function fs_get_category_colors( $term_id ) {
	if ( metadata_exists( 'term', $term_id, 'cat_color_bg' ) ) {
		$bg  = get_term_meta( $term_id, 'cat_color_bg', true );
		$txt = get_term_meta( $term_id, 'cat_color_txt', true );
	} else {
		$old = get_option( 'cat_' . $term_id ); // 一度も保存し直していないカテゴリー
		$bg  = is_array( $old ) ? ( $old['cat_color_bg'] ?? '' ) : '';
		$txt = is_array( $old ) ? ( $old['cat_color_txt'] ?? '' ) : '';
	}
	return array(
		'bg'  => (string) sanitize_hex_color( $bg ),
		'txt' => (string) sanitize_hex_color( $txt ),
	);
}

// 7. 色つきのカテゴリーボタンの HTML を返す
function fs_get_category_color_buttons( $post_id = null ) {
	$html = '';
	foreach ( get_the_category( $post_id ) as $cat ) {
		$colors = fs_get_category_colors( $cat->term_id );
		$style  = '';
		if ( $colors['bg'] ) {
			$style .= 'background-color:' . $colors['bg'] . ';';
		}
		if ( $colors['txt'] ) {
			$style .= 'color:' . $colors['txt'] . ';';
		}
		$html .= sprintf(
			'<a class="cat_btn" href="%s" rel="category tag"%s>%s</a>',
			esc_url( get_category_link( $cat ) ),
			$style ? ' style="' . esc_attr( $style ) . '"' : '',
			esc_html( $cat->name )
		);
	}
	return $html;
}

// テンプレートでそのまま出すとき
function fs_the_category_color_buttons( $post_id = null ) {
	echo fs_get_category_color_buttons( $post_id ); // 中身は上でエスケープ済み
}
書き方 役目
register_term_meta( 'category', … ) カテゴリーのタームメタ cat_color_bg・cat_color_txt を登録。sanitize_hex_color で、色のコードだけを受け付ける
category_add_form_fields カテゴリーの新規追加の画面に欄を出す
category_edit_form_fields カテゴリーの編集の画面に欄を出す。値は esc_attr で出す
wp_nonce_field と wp_verify_nonce この欄から送られたときだけ保存する。クイック編集など、ほかの保存では何もしない
current_user_can( 'edit_term', … ) そのカテゴリーを直せる人だけが保存できる
created_category・edited_category カテゴリーを足したとき・直したときだけ動く(タグなど、ほかの分類では動かない)
wp-color-picker WordPress に入っているカラーピッカーで色を選べるようにする(カテゴリーの画面だけで読み込む)
fs_get_category_colors() 色を取り出す。タームメタがまだないカテゴリーは、前のコードで保存した cat_{ID} のオプションから読む
fs_get_category_color_buttons() ボタンの HTML を返す。リンクは get_category_link で作り、名前は esc_html、style は esc_attr で出す
WordPress のカテゴリーに背景色・文字色を持たせて、色つきのボタンで出す(タームメタ・nonce・色のチェックつき)

上のコードを足すと、下のようにカテゴリーの画面に欄が増えます(画像は前のコードの入力欄です。新しいコードでは、欄をクリックするとカラーピッカーが開きます)。

style.css
.cat_btn {
	display: inline-block;
	padding: 5px 10px;
	margin: 0 10px 10px 0;
	border-radius: 5px;
	background-color: #666; /* 色を決めていないカテゴリー */
	color: #fff;
	text-decoration: none;
}

style.css には <style> のタグを書きません(前の記事のコードには書いてあり、CSS のファイルに入れると、すぐ後ろの .cat_btn の指定がまるごと効かなくなります)。色を決めていないカテゴリーは、ここの色になります。

色つきのカテゴリーボタンを出す

テンプレート(ループの中)
<?php fs_the_category_color_buttons(); ?>

文字列につないで使うときは、HTML を返す fs_get_category_color_buttons() を使います。

文字列につなぐとき
echo '<p class="date">' . fs_get_category_color_buttons( get_the_ID() ) . '</p>';

前のコードの the_category_color_btn() は、その場で echo する関数でした。上のように文字列につなぐと、ボタンが <p> の外(前)に出てしまいます。

前の書き方との違い

比べること 前の書き方 新しい書き方
保存する場所 カテゴリーごとにオプション cat_{ID} を作る(自動で読み込まれ、カテゴリーを消しても残る) タームメタ(カテゴリーを消すと一緒に消える)
色を保存していないカテゴリーの編集画面 PHP 8 で「Trying to access array offset on false」の Warning 警告なし
色の欄に色でない値 そのまま保存し、style にそのまま出す(ほかの属性を入れられる) sanitize_hex_color で空にする
クイック編集で名前を直す 色が空になる 色はそのまま
動く場所 create_term・edited_term(タグなどすべての分類) カテゴリーだけ
リンク /archives/category/ を手で書く get_category_link(パーマリンクの設定に合わせる)

確かめた結果

このサイトの作業環境(WordPress 7.1.3・PHP 8.3)で、試しのカテゴリーを作り、前のコードと新しいコードを比べました(確かめたあと、カテゴリーと作られたデータは消しました)。

試したこと 前のコード 新しいコード
色を保存していないカテゴリーの編集画面 Warning が 2 つ 警告なし
背景色に red;" onmouseover="alert(1) を保存 そのまま保存され、ボタンに onmouseover の属性が入った 空になった(#FF0000 はそのまま保存)
色の欄なしで保存(クイック編集と同じ) 背景色・文字色が空になった #1e73be・#fff のまま
nonce がちがう・権限のない人 (確かめなし) 保存しなかった
名前に & を含むカテゴリー (確かめなし) &amp; にエスケープして出た
色を空にして保存 (確かめなし) style のないボタンになった
カテゴリーを消す オプション cat_{ID} が残った タームメタも消えた
前のコードで色を保存したカテゴリー ― 前の色(例:#ae6d4c・#ffffff)を読めた
カテゴリーの画面での読み込み ― カラーピッカーを読み込み、ほかの画面では読み込まない

前のコードから入れ替えるとき

前のコードは消してから、新しいコードを入れます。両方を残すと、前のコードの保存もいっしょに動いてしまいます。

前のコードで決めた色は、新しいコードでもそのまま表示されます。カテゴリーの編集画面で一度保存すると、色がタームメタに移ります。テンプレートの the_category_color_btn( $post->ID ) は fs_the_category_color_buttons( $post->ID ) に書き換えます。

WordPress Developer Resources

関連機能

  1. WordPress のリビジョンの数を減らす・止める(wp-config.php と投稿タイプごとの設定・自動保存の間隔)

  2. WordPress 固定ページの投稿画面に新規作成したテンプレートファイルを追加する

  3. 指定期間内に公開した記事タイトルに一括で新着表示をつける

サイドバー

よく使うカスタマイズ

最近の記事

Profile

PAGE TOP