WebScripter.jpをご覧頂きありがとうございます。
このサイトについてご意見などあればお気軽にメッセージをお送り下さい。お待ちしています。



captcha

Technical note

[ WordPress ] 独自のカスタムフィールドを設定する

2014.04.23

WordPressのサイト構築で、簡単な機能はプラグインを使わずfunctions.phpに直接書いて実装することがが多くなりました。中でもカスタムフィールドが設定できると自由度が高くなりますね。独自のカスタムフィールドを設定するソースはよく紹介されてますが、ここでは流れや意味など理解を深めながら説明したいと思います。

設定の概要

次の条件でカスタムフィールドを作成することとします。

  • カスタムフィールドの名前      :天気
  • カスタムフィールドのID       :weather
  • カスタムフィールドを挿入する編集画面:投稿(post)
  • カスタムフィールドの種類      :テキストフィールド

アクションを設定する

まず管理画面にメタボックスを追加するアクションと、投稿が作成、更新された時のアクションを設定します。アクションを設定するにはadd_action()という関数を使います。

PHP
add_action( $hook, $function_to_add, $priority, $accepted_args );

パラメータは次の通り。

$hook $function_to_addで指定した関数を実行するためのアクション名(必須)
$function_to_add $hookによって実行される関数名。つまりコールバック(必須)
$priority 実行される優先順位を指定
$accepted_args $function_to_addで指定した関数のパラメータの数

add_actionでアクションを設定してみます。今回は$hookと$function_addだけで充分です。

PHP
add_action('admin_menu', 'add_weather');
add_action('save_post', 'save_weather');

上のアクションは管理画面のメニューが配置された後に(admin_menu)、編集画面にカスタムフィールドを追加する関数add_weatherを実行、下のアクションは投稿が作成、または更新された時(save_post)にデータを保存する関数save_weatherを実行するということになります。

$hookのアクションは他にも用意されているのでさらに知りたい方はプラグイン API/アクションフック一覧をご覧下さい。

管理画面に入力フィールドを追加する

入力フィールドを配置するためのメタボックスを追加する関数add_weatherを設定します。メタボックスを追加するにはadd_meta_box()を使います。

PHP
add_meta_box( $id, $title, $callback, $page, $context, $priority );

パラメータは次の通り。

$id HTML ID すなわち編集画面のHTMLに挿入されるメタボックスのdivのID (補足1参照)
$title メタボックスに表示されるタイトル
$callback メタボックスの中にHTMLを出力する関数名
$page 表示したい編集画面を指定。post(投稿) 、page(ページ) 、link(リンク) 、dashboard(ダッシュボード) 、カスタム投稿タイプ(スラッグ)のいずれかを指定
$context メタボックスを配置する場所をnormal、advanced、sideのいずれかで指定 ※2
$priority 配置される順序。highまたはlowで指定 ※2

補足1:
$idはCodexではHTML IDとあり意味がよくわからなかったんですが、$idをhogeとした場合、編集画面のソースをみると

HTML
<div id="hoge" class="postbox" >…</div>

というようにメタボックスとして作られたdivのid名に使われています。つまり追加されるメタボックスのid名ということです。

補足2
$contextのsideは指定すると編集画面の右サイドに表示されますが、normalとadvancedは実際指定してみてもどちらも左サイドに追加されるのでその違いが分からないと思います。いろいろ試してみたところ、こんな違いがあるようです。

normal $priorityのhigh、lowを指定した場合、既存のメタボックスも含めて配置される順序が決定される。
advanced 原則既存のメタボックスの後ろに追加されるが、$priorityで優先順位を指定した場合、advancedが指定されたメタボックスの中で順序が決定される。

さて、実際にadd_weatherを設定します。

PHP
function add_weather {
 add_meta_box('weather1', '天気', 'insert_weather', 'post', 'normal', 'high'); //投稿編集画面
 add_meta_box('weather2', '天気', 'insert_weather', 'page', 'normal', 'high'); //ページ編集画面
 add_meta_box('weather3', '天気', 'insert_weather', 'link', 'normal', 'high'); //リンク編集画面
 add_meta_box('weather4', '天気', 'insert_weather', 'works', 'normal', 'high'); //カスタム投稿タイプ works の編集画面(スラッグで指定)
}

次はadd_meta_boxの第3パラメータで指定した関数insert_weatherでめたボックスの中にタイトルや入力フィールドなどをHTMLで出力します。

PHP
function insert_weather(){
 global $post;
 wp_nonce_field(wp_create_nonce(__FILE__), 'wether_nonce');
 echo '<label class="hidden" for="weather">weather</label><input type="text" name="weather" size="60" value="'.get_post_meta($post->ID, 'weather', true).'" />';
 echo '<p>天気を入力します</p>';
}<

テキストボックスとラベル、説明がこれで出力されます。もちろんテキストエリアもOKです。その他のフォームのアイテム(ラジオボタンやチェックボックス、プルダウンメニューなど)についてはもう少し処理が必要になると思うので、また試してみて別の記事で紹介したいと思います。

3行目のwp_nonce_field()はリクエスト強要(CSRF)対策のためのnonceを取得、または表示するための隠しフィールドを追加します。フォームの出力から内容の保存まで一貫して自身のサイトで完了しているかどうかを検証するのに使われます。リクエスト強要(CSRF)対策やnonceについてさらに詳しい情報は以下のページで確認できます。

カスタムフィールドの入力内容を保存する

投稿が作成、更新された時の関数save_weatherを設定します。

PHP
function save_weather($post_id){
 $my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
 if(!wp_verify_nonce($my_nonce, wp_create_nonce(__FILE__))) {
  return $post_id;
 }
 if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
 if(!current_user_can('edit_post', $post_id)) { return $post_id; }
 $data = $_POST['weather'];
 if(get_post_meta($post_id, 'weather') == ""){
  add_post_meta($post_id, 'weather', $data, true);
 }elseif($data != get_post_meta($post_id, 'weather', true)){
  update_post_meta($post_id, 'weather', $data);
 }elseif($data == ""){
  delete_post_meta($post_id, 'weather', get_post_meta($post_id, 'weather', true));
 }
}

一気に書きましたが、ひとつずつ説明していきます。

PHP
$my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
if(!wp_verify_nonce($my_nonce, wp_create_nonce(__FILE__))) {
 return $post_id;
}

まず、先のinsert_weatherで設定したnonceの値を取得します。そして次の行のwp_verify_nonce()でnonceの値を比較し、値が合っていなければ処理をしません。

PHP
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }

保存される時に自動保存ルーチンかどうかを調べ、そうだった場合は処理をしません。

PHP
if(!current_user_can('edit_post', $post_id)) { return $post_id; }

current_user_can()でユーザー権限を調べ、投稿の編集権限が無ければ処理をしません。

PHP
$data = $_POST['weather'];
if(get_post_meta($post_id, 'weather') == ""){
 add_post_meta($post_id, 'weather', $data, true);
}elseif($data != get_post_meta($post_id, 'weather', true)){
 update_post_meta($post_id, 'weather', $data);
}elseif($data == ""){
 delete_post_meta($post_id, 'weather', get_post_meta($post_id, 'weather', true));
}

カスタムフィールドの値を調べ、既存のデータが無い場合は、add_post_meta()でデータの作成を、既存のデータと入力フィールドのデータが違う場合はupdate_post_meta()でデータの更新を、入力フィールドのデータが空の場合はdelete_post_meta()で既存のデータを削除します。

全体のコード

PHP
<?php
add_action('admin_menu', 'add_weather');
add_action('save_post', 'save_weather');

function add_weather(){
 if(function_exists('add_weather')){
  add_meta_box('weather1', '天気', 'insert_weather', 'post', 'normal', 'high');
 }
}

function insert_weather(){
 global $post;
 wp_nonce_field(wp_create_nonce(__FILE__), 'my_nonce');
 echo '<label class="hidden" for="weather">天気</label><input type="text" name="weather" size="60" value="'.esc_html(get_post_meta($post->ID, 'weather', true)).'" />';
 echo '<p>作成した日の天気を入力します。</p>';
}

function save_weather($post_id){
 $my_nonce = isset($_POST['my_nonce']) ? $_POST['my_nonce'] : null;
 if(!wp_verify_nonce($my_nonce, wp_create_nonce(__FILE__))) {
  return $post_id;
 }
 if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
 if(!current_user_can('edit_post', $post_id)) { return $post_id; }

 $data = $_POST['weather'];

 if(get_post_meta($post_id, 'weather') == ""){
  add_post_meta($post_id, 'weather', $data, true);
 }elseif($data != get_post_meta($post_id, 'weather', true)){
  update_post_meta($post_id, 'weather', $data);
 }elseif($data == ""){
  delete_post_meta($post_id, 'weather', get_post_meta($post_id, 'weather', true));
 }
}
?>

カスタムフィールドの値を表示する

カスタムフィールドの値を取得するには、get_post_meta()を使います。

PHP
get_post_meta($post_id, $key, $single);
$post_id データを表示したい投稿ID
$key 表示したいデータのキー
$single 指定したキーの単一の値を取得する場合はtrue、複数の値を取得する場合はfalseを指定。falseの場合は指定したキーの全ての値を配列で返す

ここでは今表示されている投稿ページの「weather」というカスタムフィールドの値がほしいので、表示したい場所に次のコードを記述します。

PHP
<?php echo get_post_meta( $post->ID , 'weather' , true ); ?>

まとめ

以上、長々と説明しましたが、独自のカスタムフィールドの追加方法をマスターすれば、Webに疎い人のための入力支援、さらに工夫すればWordpressを顧客管理や在庫管理などにも利用できると思います。改めてWordpressの自由度の高さは驚きです。

中・上級者向けですがこの2冊を購入してから、Wordpressのサイト構築の幅が広がりました。参考までに。