チェックボックスをカスタムフィールドで付ける
それほど頻繁に触らないせいか、作ろうとすると作り方を忘れていたりわからなくなっていることが多いカスタムフィールド。
今回はチェックボックスを使うために調べ直したり試したりしたことをメモ的に記載します。
実現したいこと
実現したいことは以下の通り。
- functions.phpを用いてカスタムフィールドを設定
- チェックボックスのカスタムフィールドを使用
- 複数選択を可能にする
- プラグインは使わない
なお、この機能は個人的なサイト用に作ったので、サンプルコード内の設定や項目はそのサイトの内容に準じています。
具体例用にダミーで作ると無駄に悩んで時間を食うので、その辺りの時間削減という意図もあり、一般化せずにそのままの状態で記載します。
完成予想図は以下の通りですが、実際にはこの画像は当記事末尾のプラグイン化した後の状態でして、細部は微妙に異なります。
投稿画面のチェックボックス
コード
早速ですが以下がfunctions.phpに記載するコードです。
<?php
add_action('admin_menu', 'add_tools_meta_box');
add_action('save_post', 'save_tools_custom_fields');
// メタボックス追加
function add_tools_meta_box() {
add_meta_box( 'my_sectionid', '使用ツール', 'tools_custom_fields', 'post', 'advanced' );
}
// カスタムフィールドの入力フォーム作成と値の設定
function tools_custom_fields() {
global $post;
//カスタムフィールドの値を取得
$get_tools = get_post_meta( $post->ID,'tools',true );
//値があればその値をセットし、なければ空の配列array()を設定する
$tools = $get_tools ? $get_tools : array();
//チェックボックス用の項目を設定
$data = array("不明", "鉛筆", "紙", "CLIP STUDIO PAINT", "ペンタブ", "液タブ");
?>
<?php
//下記wp_nonce_fieldの_wp_nonceは、必ず別の値に書き換える。
wp_nonce_field('wp-nonce-key', '_wp_nonce'); ?>
<?php foreach ( $data as $d ) {
//取得したデータをin_array検索 $toolsの値の中に$dataと同じ物があればcheckdを付与
if ( in_array($d, $tools) ) { $check = "checked"; } else { $check = ""; }
//複数選択の場合は、name=toolsではなくname=tools[]とする
echo '<label><input type="checkbox" name="tools[]" value="' . esc_attr($d) . '" ' . $check . '>' . esc_html($d) . '</label><br>';
} ?>
<?php
}
//保存用関数
function save_tools_custom_fields($post_id) {
if ( isset($_POST['_wp_nonce']) && $_POST['_wp_nonce'] ) {
if ( check_admin_referer('wp-nonce-key', '_wp_nonce') ) {
if ( isset($_POST['tools']) && $_POST['tools'] ) {
update_post_meta( $post_id, 'tools', $_POST['tools'] );
} else {
delete_post_meta( $post_id, 'tools', get_post_meta($post_id, 'tools', true) );
}
}
}
}
//表示用関数
function tools_used() {
if( is_single() ) {
global $post;
$html = '';
$items = '';
//get_post_meta()でシリアライズされた状態の値を通常の配列に戻しつつ取得
$items = get_post_meta( $post->ID, "tools", true );
if ( is_array($items) ) {
//implode()で配列の要素と要素の間に「/」を入れて変数に格納
$items = implode( " / ", $items );
}
if ( $items ) {
//値があった場合にhtmlを出力
$html = '<dl class="tool-list">';
$html .= '<dt>使用ツール</dt>';
$html .= '<dd>' . esc_html($items) . '</dd>';
$html .= '</dl>';
return $html;
}
}
}
テンプレートに記載する出力用の記述は以下の通り。
<?php echo tools_used(); ?>
functions.phpに記載するためのコードは、はほぼ下記のサイトを同じ内容です。
コード各所の細かい部分の説明はそちらで確認頂いたほうが良いでしょう。
その上でですが、部分的に変更しているなかでも多少記載しておいたほうが良さそうなのは以下の事柄でしょうか。
- array_searchからin_arrayに変更
- nonceフィールドの追加
array_serchとin_array
今回の動作に関しては不要だった部分を取除き、この程度であれば不要かもしれませんが速度を考えてin_arrayを使った程度です。
array_searchは動作が重い関数としてよく目にするため、大抵書換えが推奨されていましたので。
nonce フィールドの追加
カスタムフィールドなどのように値を保存する場合、WordPressでは以下のようにnonceフィールドの使用が推奨されています。
恥ずかしながらいままであまり理解できていなかったのですが、今回のコード作成時に調べて試して、少し理解できてきたかなと。
なお、nonceフィールドに関しては別記事に分けて書きたいと思いますので、詳細は以下をどうぞ。
結び
項目名の候補が確定している場合、チェックボックスの形で項目が出ている方が運用上のメリットがあるのではと考えて作りました。
現在はプラグイン化
この記事を書いたのは公開の2ヶ月程前でして、その後プラグイン化の練習を兼ねて更に改良し、管理画面からチェックボックスの項目を設定出来るようにしました。
当記事上部の「構築環境」という部分が該当します。
管理画面のプラグイン設定画面
カンマ区切りの配列でチェックボックスを設定できるようにしてあるので、項目は簡単に増やせて便利かなと。
役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。
連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。
全くできずにどうやってもエラーが出ました。
結構前に作ったままなので、現在では問題あるかもしれません。または記事内の記述にミスがあることも考えられますが。
とはいえエラーに従って直していただけると動作するかもしれませんので、当記事のコードを利用する場合はエラー修正を試されることをお勧めします。
最初のadd_actionの第2引数ですが、add_tools_boxではなく、add_tools_meta_boxではないでしょうか?
確かに書き間違っていますね…。
ブログに記載する際の調整で書き間違えたのだとは思いますが気づいていませんでした。
ご指摘いただきありがとうございます。
add_tools_meta_boxに書き直しました。