カスタムフィールドとメタボックスの動き(値の操作について)
Wordpressオリジナルテーマに自作したメタボックスを、デフォルトのカスタムフィールドのように、動的に複数個に増やしていきたいと思い、まず従来のカスタムフィールドの動きを確認する。
目的
メタボックスを自作する上で、既存に存在するカスタムフィールドのように投稿によってボタンを押したら入力欄が増える、のような事をしたくて 動的に複数のカスタムフィールドを作成できる方法を模索する。 カスタムフィールドのソースコードを漁ったりもしようとしたのですが、個人のスキル不足の問題でぱっと見てすぐ解析できず、時間がかかりそうだったので、 とりあえず自分で作ってみようかなと思ったので、まずメタボックスとカスタムフィールドがDBへどのように格納されるかの確認をする。 以下、疑問点
- カスタムフィールドとメタボックスはDB内のどのテーブルに値を保存するのか?(一緒?)
- カスタムフィールドはどのタイミングで値を更新しているのだろうか?(仮にsave_post時だとレコードの増減を判別しなきゃ?)
- カスタムフィールドは更新するためのレコードの判別を何でしているのか?(レコードを一意に認識するために、GUIにhiddenでmeta_idを隠し持っておくべきか)
結果
とりあえず、わかったこと、 ※個人の検証環境で行った結果のため必ずそうとは言い切れないです。(メタボックスとか自分で書いたやつだし) ・Wordpressのバージョン WordPress 5.1.1 ・メタボックスの値の保存方法はadd_post_meta()を使用 ・メタボックスの値の保存方法はsave_postにフックする ・カスタムフィールドはデフォルト
- 値の格納先について、カスタムフィールドとメタボックスの値はpostmetaテーブルに格納される
- 値の更新について、カスタムフィールドはGUIの「カスタムフィールドを追加」ボタン等を押した時点でpostmetaテーブルに値が反映される
- 重複した値について、カスタムフィールドは同じmeta_keyを許している
- 重複した値の取得について、get_post_meta()でポスト内の同じmeta_keyの値を配列で取得できる
- 重複した値の更新について、get_post_meta()やget_metadata()などの関数ではmeta_idを取得できない
- 重複した値の更新について、delete_post_meta()などはmeta_idで判別しているわけではなく、meta_valueで判別している?
自分でつくるなら、カスタムフィールドのようにGUIからの「追加」、「削除」、「更新」ボタン操作でAJAXなどを使用して更新、 重複したmeta_keyのレコード判別はmeta_valueにしようかな、と思う。 meta_valueが同じ値だった場合とか懸念点は多そうだけど、とりあえず試しにまず動くものを作ってみようかなと、思う。 とりあえずこの記事では検証した内容だけをメモ。
方法(検証手順)
フロー(検証手順)
1メタボックスを作成、値を保存 |
↓ |
2デフォルトのカスタムフィールドを使って値を保存 |
↓ |
3カスタムフィールドの値を更新、DBとWordpress関数で確認する |
まず、postmetaテーブルを確認する。 meta_keyがUNIQUEじゃないのが気になる。
mysql> DESC xxxxpostmeta;
+------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------------+------+-----+---------+----------------+
| meta_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| post_id | bigint(20) unsigned | NO | MUL | 0 | |
| meta_key | varchar(255) | YES | MUL | NULL | |
| meta_value | longtext | YES | | NULL | |
+------------+---------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
メタボックスを作成、値を保存
以前に書いた以下の記事をそのまま使用する。
WordPressでカスタム投稿タイプとメタボックスを使用して独自の投稿画面を作成する方法カスタムフィールドの値を更新、DBとWordpress関数で確認する
GUIでこのような形で入力する。メタボックスで保存した値
ポストID81の中で独自に作成したメタボックスに値をいれた場合のpostmetaテーブル meta_keyはメタボックス作成時に任意で作成した値、以下$keyの部分
add_post_meta($post_id, $key, $value, true);
mysql> select * from xxxxpostmeta WHERE meta_key REGEXP "_articles.*" AND post_id = 81;
+---------+---------+--------------------+--------------------------------------------------------------------------------------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+--------------------+--------------------------------------------------------------------------------------------------------------+
| 97 | 81 | _articles-subtitle | WordPressのウィジェットを使用するためのオリジナルのサイドバーを自作します。 |
| 110 | 81 | _articles-memo | ここはメモです |
+---------+---------+--------------------+--------------------------------------------------------------------------------------------------------------+
カスタムフィールドで保存した値
ポストID 92の中でデフォルトのカスタムフィールドに値をいれた場合のpostmetaテーブル 記事を保存しなくても、カスタムフィールドを追加、削除した時点でpostmetaテーブルを更新する。 当然かもしれないがポストID 92を削除すると全て消える。
カスタムフィールド追加時(137と138を追加した)(GUIから「カスタムフィールドを追加」ボタン)
mysql> select * from xxxxpostmeta WHERE post_id = 92;
+---------+---------+---------------------------+---------------------------------+
| 133 | 92 | _edit_lock | 1562442297:1 |
| 135 | 92 | _edit_last | 1 |
| 136 | 92 | _encloseme | 1 |
| 137 | 92 | カスタムサンプル | カスタムサンプルの値 |
| 138 | 92 | カスタムサンプル2 | カスタムサンプル2の値 |
+---------+---------+---------------------------+---------------------------------+
5 rows in set (0.00 sec)
カスタムフィールド削除時(138を削除した)(GUIから「削除」ボタン)
mysql> select * from xxxxpostmeta WHERE post_id = 92;
+---------+---------+--------------------------+--------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+--------------------------+--------------------------------+
| 133 | 92 | _edit_lock | 1562442297:1 |
| 135 | 92 | _edit_last | 1 |
| 136 | 92 | _encloseme | 1 |
| 137 | 92 | カスタムサンプル | カスタムサンプルの値 |
+---------+---------+--------------------------+--------------------------------+
4 rows in set (0.00 sec)
新たにカスタムフィールド追加時(139となって追加された)(GUIから「カスタムフィールドを追加」ボタン)
mysql> select * from xxxxpostmeta WHERE post_id = 92;
+---------+---------+---------------------------+---------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+---------------------------+---------------------------------+
| 133 | 92 | _edit_lock | 1562442357:1 |
| 135 | 92 | _edit_last | 1 |
| 136 | 92 | _encloseme | 1 |
| 137 | 92 | カスタムサンプル | カスタムサンプルの値 |
| 139 | 92 | カスタムサンプル3 | カスタムサンプル3の値 |
+---------+---------+---------------------------+---------------------------------+
5 rows in set (0.00 sec)
同じmeta_keyでも登録可能
mysql> select * from xxxxpostmeta WHERE post_id = 92;
+---------+---------+---------------------------+---------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+---------------------------+---------------------------------+
| 133 | 92 | _edit_lock | 1562442357:1 |
| 135 | 92 | _edit_last | 1 |
| 136 | 92 | _encloseme | 1 |
| 137 | 92 | カスタムサンプル | カスタムサンプルの値 |
| 139 | 92 | カスタムサンプル3 | カスタムサンプル3の値 |
| 140 | 92 | カスタムサンプル | カスタムサンプルの値2 |
+---------+---------+---------------------------+---------------------------------+
wordpress関数を使った取得
カスタムフィールドが同じmeta_keyを許すことから、カスタムフィールドを一意のものと認識するためにはmeta_idが必要だと思い、Wordpress関数でメタデータを取得するとどのような値をとってきているのかを確認する。
▼get_post_meta()(meta_keyの引数あり)
get_post_meta()で同じポスト内で重複しているmeta_keyを引数として与えると、1つしかとれない
// 実行文
//echo "<pre>";
//var_dump(get_post_meta($post->ID, 'カスタムサンプル' , true)) ;
//echo "</pre>";
string(30) "カスタムサンプルの値"
▼get_post_meta()(meta_keyの引数あり)
get_post_meta()で第3引数をfalseにすると重複した値を配列にいれてくる。しかしmeta_idは取得できない
// 実行文
//echo "<pre>";
//var_dump(get_post_meta($post->ID, 'カスタムサンプル' , false)) ;
//echo "</pre>";
array(2) {
[0]=>
string(30) "カスタムサンプルの値"
[1]=>
string(31) "カスタムサンプルの値2"
}
▼get_post_meta()(meta_keyの引数なし)
get_post_meta()(meta_keyの引数なし)ではmeta_idは取得できない。値は全て配列として格納されている
// 実行文
//echo "<pre>";
//var_dump(get_post_meta($post->ID)) ;
//echo "</pre>";
array(5) {
["_edit_lock"]=>
array(1) {
[0]=>
string(12) "1562442357:1"
}
["カスタムサンプル"]=>
array(2) {
[0]=>
string(30) "カスタムサンプルの値"
[1]=>
string(31) "カスタムサンプルの値2"
}
["カスタムサンプル3"]=>
array(1) {
[0]=>
string(30) "カスタムサンプル3の値"
}
["_edit_last"]=>
array(1) {
[0]=>
string(1) "1"
}
["_encloseme"]=>
array(1) {
[0]=>
string(1) "1"
}
}
▼get_metadata()
get_metadata()でも変わらず
// 実行文
//echo "<pre>";
//var_dump(get_metadata( 'post', $post->ID ));
//echo "</pre>";
array(5) {
["_edit_lock"]=>
array(1) {
[0]=>
string(12) "1562442357:1"
}
["カスタムサンプル"]=>
array(2) {
[0]=>
string(30) "カスタムサンプルの値"
[1]=>
string(31) "カスタムサンプルの値2"
}
["カスタムサンプル3"]=>
array(1) {
[0]=>
string(30) "カスタムサンプル3の値"
}
["_edit_last"]=>
array(1) {
[0]=>
string(1) "1"
}
["_encloseme"]=>
array(1) {
[0]=>
string(1) "1"
}
}
▼get_post_custom_values()
get_post_custom_values()ならどうだと思い、しかし変わらず
// 実行文
//echo "<pre>";
//var_dump(get_post_custom_values('カスタムサンプル',$post->ID));
//echo "</pre>";
array(2) {
[0]=>
string(30) "カスタムサンプルの値"
[1]=>
string(31) "カスタムサンプルの値2"
}
postmetaテーブルの同じpost内でmeta_key重複した値を識別する方法
delete_post_meta()の仕様をみると重複したキーは値で判断している?
▼delete_post_meta()
値 | 説明 |
---|---|
$post_id | (整数)(必須) 削除したいカスタムフィールドを持つ投稿の ID |
$meta_key | (文字列)(必須) 削除したいカスタムフィールドのキー。 |
$meta_value | (mixed)(オプション) 削除したいカスタムフィールドの値。これは、同じキーを持つカスタムフィールドを区別するパラメータです。省略すると、指定したキーを持つカスタムフィールドはすべて削除されます。 |
戻り 値 | (真偽値) 失敗なら False、成功なら True を返す。 |
とりあえず、わかったことはカスタムフィールドは管理画面の「公開」ボタンなどがトリガーで保存されているわけではない、ということ、 meta_keyが重複しても大丈夫なことと、delete_post_meta()を参考として見る限り、meta_valueとmeta_keyでレコードを一意に認識できること、 かなと、 それを踏まえ、もし自分で作るなら、レコードの追加、削除、変更は従来のカスタムフィールドと同じく、「公開」ボタンをトリガーとはせず、 各々の「削除」、「追加」ボタンを作成して、それをトリガーにしようと思う。 またdelete_post_meta()などで、postmetaテーブルの更新するレコードをある程度しぼれそうなので、その関数たちを遣う。(直接クエリ文とかを書かない) 記事編集画面を開いた場合に出力する、postmetaテーブルの値はget_post_meta()などで配列で持ってくる。 あまり結果が変わらなかったので書かないがWP_QUERYにもmeta_idは入っていないように思われる、