【WordPress】カスタムフィールドを利用する

【WordPress】カスタムフィールドを利用する

今回はwordpressでカスタムフィールドを利用する方法についてみていきたいと思います。

カスタム投稿、カスタムタクソノミーと続き、カスタムフィールドです。

今回はコードでの説明を行いますが、プラグインで良いものが多いためプラグインを使用したカスタムフィールドの取り扱いも後日記事にしたいと思います。

今回はカスタムフィールドの使用としては多いと思われるカスタム投稿にカスタムフィールドを実装していく場合で記述していきます。

画像なども使用しながら、どこに使用されるのかわかりやすいよう伝えていきたいと思います。

また、カスタムフィールドで、一つのキーに100件分の情報が入っているもの、100件のキーにひとつづつ情報が入っている物と取得の際の時間も計測しみます

カスタムフィールドを作成する

カスタムフィールドはそれぞれの投稿に紐づいた情報などを保存する際に使用します。

wp_postmetaに投稿IDとカスタムフィールドのkeyとvalueが保存されます。

keyとvalueを設定するだけなので、構造的にも簡単で使用しやすいです。

以下の流れで作成していきます。

メタボックスの作成

    ⇓

メタボックス内容の保存

この二つを準備することで、投稿画面からカスタムフィールドの登録を行うことができるようになります。

もし、csv等でカスタムフィールドを流し込みを行い、編集の必要がないのであればメタボックスの作成は行わなくてもよいと思います。

それぞれについて見ていきます。

メタボックスの作成

メタボックスの作成には以下の関数を使用します。

また、関数は「add_meta_boxes」にアクションフックさせます。

add_meta_box( $id, $title, $callback, $screen, $context, $priority, $callback_args )

各引数には以下の通りです。

$id

(string) ボックスのhtml ID

$title

(string) ボックスに表示されるタイトル

$callback

実際にメタボックスを構成する関数名

$screen

(string / array)メタボックスを表示する場所

‘post’ ‘page’など文字列で指定するか配列で指定。カスタム投稿タイプの場合はカスタム投稿名を指定。

初期値: null (nullの場合get_current_screenが適応される)

$context

(string) メタボックスの表示位置

初期値: advanced

$priority

(string) ボックスの表示優先度(‘default’,’low’,’high’)

初期値: default

$callback_args

(array) コールバック関数が受け取る引数を配列で指定。

初期値: default

実際の例を見てみます。

カスタム投稿タイプ「coffee」に「200gあたりの値段」を設定する項目を表示させたいと思います。

add_action( 'add_meta_boxes', function() {
	add_meta_box(
		'coffee_info',
		'コーヒー情報欄',
		'coffee_info_box',
		'coffee',
		'side'
	);
} );

function coffee_info_box( $post ) {
	wp_nonce_field( 'coffee_nunce_action', 'coffee_nunce_field' );

	$value = get_post_meta( $post->ID, 'coffee_price_key', true );

	ob_start();
	?>
	<div class="coffee-title">
		<label for='coffee-price'>値段(200g)</label>
	</div>
	<div class="coffee-content">
		<input type="text" name='coffee-price' value="<?php echo esc_attr( $value ) ?>" />
	</div>	
	<?php
	echo ob_get_clean();
}

「get_post_meta」で変更前の現在の状態を取得し、初期値として表示させています。

get_post_meta( $post_id, $key, $single);

$singleには同じキーで値が複数入っていた場合の取得方法を指定します。

true」・・・配列の[0]を取得

false」・・・配列ごと取得(デフォルト)

上記のように入力することで以下のような表示になります。

現在の状態では入力はできますが、保存はされない状態となっています。なので次に保存の処理についてみてみましょう。

メタボックス内容の保存

メタボックスに入力された内容を保存する方法を見ていきます。

一般的には投稿が保存されたときに行われる「save_post」にアクションフックし、カスタムフィールドの値を保存します。

上のメタボックスを保存する場合だと以下のようになります。

add_action( 'save_post', function( $post_ID ) {
	
	$post_type = get_post_type( $post_ID );
	if( !( $post_type == 'coffee' ) ) {
		return;
	}

	if( !isset( $_POST['coffee_nunce_field'] ) || 
		!wp_verify_nonce( $_POST['coffee_nunce_field'], 'coffee_nunce_action' ) ) {
		return;
	}

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}

	if( isset( $_POST['coffee-price'] ) ) {
		$sanitize_value = sanitize_text_field( $_POST['coffee-price'] );
		update_post_meta( $post_ID, 'coffee_price_key', $sanitize_value );
	}
	
} );

上から、投稿タイプのチェック、ナンスのチェック、自動保存のチェック、値のチェックとなっています。

投稿タイプのチェック・・・投稿タイプが「coffee」でないときは何もしません。

ナンスのチェック・・・ナンスが政党でないときは保存しません。

自動保存のチェック・・・自動保存の時は保存を行いません。

値のチェック・・・POST内にあった場合のみ保存を行います。

また、ここで独自のデータ加工など行う場合は処理を挿入します。

チェックが終了したら「update_post_meta」で更新をしています。

update_post_meta( $post_id, $meta_key, $meta_value, $prev_value);

指定された投稿データのメタキーが登録されているか調べ、登録されていたら「更新処理」を、登録されていなかったら「新規追加処理」が行われます。

キーに紐づいた値が複数ある際などは「$prev_value」を指定しないとキーに紐づいたすべての値が「$meta_value」に変更されますので注意してください。

これで入力欄に入力した内容が保存され、カスタムフィールドとして機能します。

カスタムフィールドの利用

カスタムフィールドの利用には上記で出てきた「get_post_meta」を利用することが多いです。

その他には指定した投稿IDのカスタムフィールドのキーと値を一括取得する「get_post_custom($post_id)」というものもあります。

実質的には「get_post_meta」のキーを指定しない、投稿IDのみ指定した時と同じ挙動です。

一括で取得することはできますが、値が配列の場合シリアル化されたまま取得されるので「unserialize」でシリアル化を復元する必要があります。

また、カスタムフィールドで保存した値を利用し、出力する場合にはサニタイズ処理を行うようにしましょう。

カスタムフィールドの検証

カスタムフィールドは大量に実装することで重いといった物を見かけたことがあったので軽くですが検証してみようと思います。

実際にありそうな100件のデータに対して以下を行います。

  • 1件ずつキーを持たせて1件ずつ取得する。
  • 100件分を連想配列で1件の値とし、1件のキーで取得する。
  • 1件のキーに100件分の情報を与え、1件のキーで取得する。
  • (一括取得する)

以下のコードでデータを格納してみました。

delete_post_meta(7,'test_2');  //3番目用
for( $i = 1 ; $i <= 100 ; $i++) {
	update_post_meta(7, 'test'. $i, $i); //1番目(多キー1値)
	add_post_meta(7, 'test_2', $i); //3番目(1キー多値)
	$str['test'.$i] = $i; //2番目用連想配列
}
update_post_meta(7,'test',$str); 2番目(1キー1値)

1番目はfor分で1回ずつ「get_post_meta」を行います。

2番目3番目は「get_post_meta」でキー指定、一括取得は「get_post_meta」で投稿IDのみ指定しました。

結果は多少差はあれど各値の開き具合は同じで以下のようでした。

(micritime(true)で計測しています。)

  • 0.00049495697021484
  • 4.1961669921875E-5
  • 5.0067901611328E-5
  • 4.0531158447266E-6

みなさんの想像の通りではないかと思います。

多キー1値はいちばん時間がかかっています。

やはり1キー1値は早いですね。100件の結果ですが10倍近い差が出ています。

一括取得はいちばん取得数が多いですが、一番早いですね。圧倒的です。

結論

DBへの接続回数が多いほど時間はかかるということですね。

取得する際は一度に取得するのがよさそうです。

一括取得が一番早いのは上でもあげたようにシリアル化の復元を行っていないからだと考えられます。(キー指定しない場合シリアル化処理前にreturnされている)

ちなみに1000件で試したところかなり重くなり、1番目と2、3番目では50倍近く差が開きました。また、一括取得では計測時間は変わりませんでした。