当サイトはアフィリエイト広告を利用しています

[WordPress]カスタムフィールドを自作する手順

カスタムフィールドを自作する手順を記します。

ちなみにカスタムフィールドとは画像の赤枠部分。

ここにメタボックスという、独自の領域を作成し、内側に入力フォームを用意していきます。


参考
カスタムフィールドの使い方Codex

作成するサンプル

今回、説明で使用するサンプルはこちら。

赤枠の部分が作成するメタボックス。
そこで入力したテキスト(色指定)を青枠のショートコードで出力します。
出力したプレビュー画面がこちら。

サンプルのソースコード全文。
動作確認する場合はfunctions.phpにコピペしてください。

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'を指定しています。
入力フォームの作成はそちらのコールバックで行います。


参考
関数リファレンス/add meta boxCodex


参考
プラグイン 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で保存をするようにします。


参考
$_POSTPHP.net


参考
関数リファレンス/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 = [];
}

このようにクラスの配列もそのまま保存、取得ができます。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です