カスタムフィールドを自作する手順を記します。
ここにメタボックスという、独自の領域を作成し、内側に入力フォームを用意していきます。
作成するサンプル
今回、説明で使用するサンプルはこちら。
赤枠の部分が作成するメタボックス。
そこで入力したテキスト(色指定)を青枠のショートコードで出力します。
出力したプレビュー画面がこちら。
サンプルのソースコード全文。
動作確認する場合はfunctions.phpにコピペしてください。
//==============================================================================
//
// カスタムフィールドテスト(文字列出力)
// カスタムフィールドのテキストに入力された文字列をショートコードで出力します。
//
//==============================================================================
//--------------------------------------------------------------
// アクションフックに登録:管理画面にカスタムボックスをエントリー
//--------------------------------------------------------------
add_action(
'add_meta_boxes',
function(){
$screens = array('post', 'page'); //投稿ページと固定ページに表示
foreach($screens as $scrn){
add_meta_box(
'peralab-custombox-print-hello', //編集画面セクションのHTML ID
'ショートコードでテキスト出力', //メタボックスのタイトル
'PeralabHello_CustomBoxCreate', //入力フォーム作成で呼び出されるコールバック
$scrn, //表示するページ
'normal', //メタボックス表示箇所(advanced, normal, side)
'default', //表示優先度(high, core, default, low)
null); //コールバック時に渡す引数があれば指定
}
}
);
//--------------------------------------------------------------
// メタボックスを作成
//--------------------------------------------------------------
function PeralabHello_CustomBoxCreate($post){ //$postには現在の投稿記事データが入っています
//入力済みのデータを取得
$data_str = get_post_meta($post->ID, "hello_item_string", true);
//初回の場合、データが入っていないので空チェック
//get_post_metaの第3引数がtrue指定の場合、データが無い時は空文字列になっています
if($data_str == ''){
$data_str = 'ここにテキストを入力';
}
//色データを取得
$data_color = get_post_meta($post->ID, "hello_item_color", true);
if($data_color == ''){
$data_color = 'black';
}
//nonce作成
wp_nonce_field('action-noncekey-sample', 'noncename-sample');
?>
<div>
<!-- 出力する文字列 -->
<label for="id-metabox_hello_text">出力文字列</label>
<input id="id-metabox_hello_text" name="name-metabox_hello_text" type="text" size="35" value="<?php echo esc_attr($data_str); ?>">
<!-- カラー指定のプルダウンメニュー -->
<label for="id-metabox_hello_color">文字色</label>
<select id="id-metabox_hello_color" name="name-metabox_hello_color" size="1">
<?php
$menu_list = [['black', '黒'], ['red', '赤'], ['blue', '青']];
foreach($menu_list as $menu){
$selected = ($menu[0] == $data_color) ? 'selected' : '';
echo "<option value=\"{$menu[0]}\" $selected>{$menu[1]}</option>";
}
?>
</select>
</div>
<?php
}
//--------------------------------------------------------------
// カスタムボックス内のフィールド値更新処理
//--------------------------------------------------------------
add_action(
'save_post',
function($post_id){
//nonceを確認
if(isset($_POST['noncename-sample']) == false
|| wp_verify_nonce($_POST['noncename-sample'], 'action-noncekey-sample') == false) {
return; //nonceを認証できなかった
}
//自動保存ルーチンかどうかチェック。そうだった場合はフォームを送信しない(何もしない)
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
return;
}
//パーミッション確認
if(isset($_POST['post_type'])){
if($_POST['post_type'] == 'page'){
if(!current_user_can('edit_page', $post_id)){
return; //固定ページを編集する権限がない
}
}
else{
if(!current_user_can('edit_post', $post_id)){
return; //記事を編集する権限がない
}
}
}
//== 確認ここまで ==
//予約投稿時は、データが有るにも関わらず$_POSTからデータ取得ができないので、
//issetでデータ確認が出来るときのみ値の更新処理を行います。
if(isset($_POST['name-metabox_hello_text'])){
update_post_meta($post_id, "hello_item_string", $_POST['name-metabox_hello_text']);
}
if(isset($_POST['name-metabox_hello_color'])){
update_post_meta($post_id, "hello_item_color", $_POST['name-metabox_hello_color']);
}
}
);
//=========================
// ショートコード
//=========================
add_shortcode(
'metabox_sample_print',
function(){
$data_str = get_post_meta(get_the_ID(), "hello_item_string", true);
if($data_str == '') $data_str = 'テキストが入力されていません';
$data_color = get_post_meta(get_the_ID(), "hello_item_color", true);
if($data_color == '') $data_color = 'black';
return "<p style=\"color:{$data_color}\">{$data_str}</p>";
}
);
メタボックスの作成
アクションフックを利用してメタボックスを作成します。
使用するアクションは 'add_meta_boxes'
add_action(
'add_meta_boxes',
function(){
$screens = array('post', 'page'); //投稿ページと固定ページに表示
foreach($screens as $scrn){
add_meta_box(
'peralab-custombox-print-hello', //編集画面セクションのHTML ID
'ショートコードでテキスト出力', //メタボックスのタイトル
'PeralabHello_CustomBoxCreate', //入力フォーム作成で呼び出されるコールバック
$scrn, //表示するページ
'normal', //メタボックス表示箇所(advanced, normal, side)
'default', //表示優先度(high, core, default, low)
null); //コールバック時に渡す引数があれば指定
}
}
);
上記コードだと、投稿ページと固定ページの場合にメタボックスを作成するようにしています。
コールバック関数に'PeralabHello_CustomBoxCreate'を指定しています。
入力フォームの作成はそちらのコールバックで行います。
参考
プラグイン API/アクションフック一覧/add meta boxesCodex
入力フォームの作成
function PeralabHello_CustomBoxCreate($post){ //$postには現在の投稿記事データが入っています
//入力済みのデータを取得
$data_str = get_post_meta($post->ID, "hello_item_string", true);
//初回の場合、データが入っていないので空チェック
//get_post_metaの第3引数がtrue指定の場合、データが無い時は空文字列になっています
if($data_str == ''){
$data_str = 'ここにテキストを入力';
}
//色データを取得
$data_color = get_post_meta($post->ID, "hello_item_color", true);
if($data_color == ''){
$data_color = 'black';
}
//nonce作成
wp_nonce_field('action-noncekey-sample', 'noncename-sample');
?>
<div>
<!-- 出力する文字列 -->
<label for="id-metabox_hello_text">出力文字列</label>
<input id="id-metabox_hello_text" name="name-metabox_hello_text" type="text" size="35" value="<?php echo esc_attr($data_str); ?>">
<!-- カラー指定のプルダウンメニュー -->
<label for="id-metabox_hello_color">文字色</label>
<select id="id-metabox_hello_color" name="name-metabox_hello_color" size="1">
<?php
$menu_list = [['black', '黒'], ['red', '赤'], ['blue', '青']];
foreach($menu_list as $menu){
$selected = ($menu[0] == $data_color) ? 'selected' : '';
echo "<option value=\"{$menu[0]}\" $selected>{$menu[1]}</option>";
}
?>
</select>
</div>
<?php
}
コールバックの引数に$postが渡されて、現在の投稿記事のデータが入っています。
$post->IDで投稿IDが取得できます。
初回以外はデータが入力済みのため、フォーム作成時も入力済みのデータを反映させるようにします。
get_post_meta($post->ID, $key, $single) 関数でデータベースからデータを取得します。
$keyはデータベースに保存しているキー名です。
後述するデータベースに値を保存するupdate_post_meta関数で指定したのと同じ$keyを使用します。
$single はtrueを指定すれば文字列として単一の値を取得できます。クラスや配列を保存していた場合も、保存した時、そのままの形で受け取れます。
falseの場合はカスタムフィールド全体の値を配列として受け取れます。
var_dumpなどで値を出力してみると分かりやすいかと思います。
今回のサンプルでは true で単一の値として受け取ります。
get_post_metaで受け取った値は、空の場合もあるので使用前に必ず空チェックをします。
$single をtrue指定の場合、空データは '' の空文字で返ってきます。
また、入力フォームのセキュリティ対策として、wp_nonce_field関数を使ってnonceを作成しています。
参考
関数リファレンス/get post metaCodex
参考
関数リファレンス/wp nonce fieldCodex
入力フォームの値更新処理
add_action(
'save_post',
function($post_id){
//nonceを確認
if(isset($_POST['noncename-sample']) == false
|| wp_verify_nonce($_POST['noncename-sample'], 'action-noncekey-sample') == false) {
return; //nonceを認証できなかった
}
//自動保存ルーチンかどうかチェック。そうだった場合はフォームを送信しない(何もしない)
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){
return;
}
//パーミッション確認
if(isset($_POST['post_type'])){
if($_POST['post_type'] == 'page'){
if(!current_user_can('edit_page', $post_id)){
return; //固定ページを編集する権限がない
}
}
else{
if(!current_user_can('edit_post', $post_id)){
return; //記事を編集する権限がない
}
}
}
//== 確認ここまで ==
//予約投稿時は、データが有るにも関わらず$_POSTからデータ取得ができないので、
//issetでデータ確認が出来るときのみ値の更新処理を行います。
if(isset($_POST['name-metabox_hello_text'])){
update_post_meta($post_id, "hello_item_string", $_POST['name-metabox_hello_text']);
}
if(isset($_POST['name-metabox_hello_color'])){
update_post_meta($post_id, "hello_item_color", $_POST['name-metabox_hello_color']);
}
}
);
値の更新(保存)はアクションフック 'save_post' に関数を登録して行います。
記事を保存した時や、公開した時に呼び出されます。
引数には $post_id(投稿記事ID)が渡されます。
実際に値を保存する前に、保存しても問題ないデータなのかを確認します。
wp_verify_nonce関数でnonceが確実に自分で作成した入力フォームからのデータであることをチェックしています。
次に自動保存によるデータ保存なのか確認しています。
今回のプラグインは自動保存の場合、何もせず処理を終えるようにしています。
パーミッション(権限)の確認を行います。
ユーザーが編集権限を持っていないのならば、保存処理をしません。
確認はここまでです。
では、値の更新(保存)処理を行います。
フォームに入力されている値は、$_POST['name'] で取得できます。
'name'は入力フォームの各パーツにつけている name を指定します。
未入力の場合は、キー自体が存在しないため、取得前にissetでデータの存在を確認します。
データベースへの値の更新(保存)処理
update_post_meta($post_id, $key, $meta_value);
$keyはデータベースに保存するキー名を指定します。
ここで指定したキー名でget_post_metaで値を取得できます。
$meta_valueに保存するデータを渡します。
値の保存用にはadd_post_meta関数もありますが、新規追加のみで、値の更新処理に対応していません。
update_post_metaはデータがあれば更新し、新規データの場合は内部でadd_post_meta関数を呼び出します。
そのため、ほとんどのケースはupdate_post_metaだけで事足りると思われます。
注意点として、予約投稿時は$_POSTのデータが、値が存在していても取得失敗となってしまうため、その対処を入れます。
issetで$_POSTに値の存在確認(データが取得できる)をしてからupdate_post_metaで保存をするようにします。
参考
関数リファレンス/update post metaCodex
参考
関数リファレンス/add post metaCodex
参考
関数リファレンス/wp verify nonceCodex
ショートコードからカスタムフィールド値を利用する
add_shortcode(
'metabox_sample_print',
function(){
$data_str = get_post_meta(get_the_ID(), "hello_item_string", true);
if($data_str == '') $data_str = 'テキストが入力されていません';
$data_color = get_post_meta(get_the_ID(), "hello_item_color", true);
if($data_color == '') $data_color = 'black';
return "<p style=\"color:{$data_color}\">{$data_str}</p>";
}
);
入力フォーム作成時と同様に、get_post_meta関数で取得します。
投稿IDはget_the_ID()で現在の投稿IDを取得します。
ここでもデータベースが空の場合がありえるので、空チェックは行います。
以上で、完成です。
データベースにはクラスや配列も保存出来る
上記サンプルでは単一の文字列をデータベースに保存していましたが、クラスや配列もそのまま保存出来ます。
クラスや配列はupdate_post_metaの時に、シリアライズされて保存され、get_post_metaでデシリアライズされます。
クラスの場合
class ItemData{
public $text_str = '';
public $text_color = 'black';
}
//値の更新(保存)
$data = new ItemData();
update_post_meta($post_id, 'key_class', $data);
//値の取得
$data = get_post_meta($post->ID, 'key_class', true);
if($data == ''){ //空チェック
$data = new ItemData();
}
空チェックはクラスの場合でも、get_post_metaの第3引数にtrueを指定していれば空文字が返ってくるので == '' で確認します。
配列の場合
//値の更新(保存)
$items = [];
for($i = 0; $i < 10; $i++){
$post_data = new ItemData();
$post_data->text_str = "番号:{$i}";
$items[] = $post_data;
}
update_post_meta($post_id, 'key_array', $items);
//値の取得
$items = get_post_meta($post->ID, 'key_array', true);
if($items == ''){ //空チェック
$items = [];
}
このようにクラスの配列もそのまま保存、取得ができます。