カスタムフィールドの投稿入力フォームへの表示
この記事は公開または最後に更新されてから2641日が経過しています。情報が古くなっている可能性があるのでご注意下さい。
とてもありがたい秀逸なプラグイン、カスタムフィールドテンプレートを使えば、入力フォームを投稿入力フォームやクイック編集フォームに表示してくれます。でも、ふとプラグインを使わなければ出来ないものだろうかと。
ネットで調べてみるとやはりありがたい情報を提供してくださるサイトが多々ありまして。
- 『編集画面に独自のカスタムフィールドの入力項目を追加する | Web Design Leaves』
- 【wordpress】カスタム投稿タイプとカスタムフィールドでカスタマイズ |制作現場のコードストック||つながるねっと
特に勉強させていただいたほんとにありがたいのは上記サイト。
そのほかにも色々と参考にさせていただきながら自分に都合の良いように作ってみました。
とりあえず、カスタムフィールドの情報を配列で定義しておくと後々使い勝手が良くて便利ということなのでそれを。
フォームとして出力する時に、データを判別して使えるような配列にしてあります。
配列のキーとしたのはカスタムフィールド名。最初のデータにform のinput ボックスのname 属性に使う文字列。POST送信される時にデータの判別子となる文字列です。
通常の投稿postとカスタム投稿diysでカスタムフィールドを使っているため、それぞれの投稿フォームにおいて出力するカスタムフィールド入力フォームを変更するために投稿の種類もデータに入れます。そのほうが後々追加することがあってもやりやすいのではないかと。
※カスタムフィールドの情報の配列において、1:の「取得データ形式」について
カスタムフィールドは1つの投稿に対して、同じキーを持つ値を複数保存することができます。この場合データベース上( wp_postmeta テーブル)には同じpost_id 、同じmeta_key を持つデータが複数存在しています。
一方、add_post_meta() を使用すれば、1つのデータに配列の値を保存することもできます。この場合、そのデータは当然のことながらシリアライズされた状態で格納されています。シリアライズは説明がややこしいのでご自分で調べましょう。
そして、この「取得データ形式」の値というのは、いざ、カスタムフィールドのデータをget_post_meta( $post_id, $key, $single ) で取得する時に、その3つ目の引数を指定する際に使用する値です。
この3つ目の引数、$single を省略するかまたは false を指定すると戻り値は配列となります。仮にそのキーの値が1つしかなくても配列の状態になっています。ある値が配列で保存されていれば、アンシリアライズされた多次元の配列が返されます。
一方、$single をtrue に設定すれば、その戻り値は単純な1つの文字列です。そのキーの値が1つだけしかなければなんら支障はありません。しかし値が複数あったり、配列の値があったりした場合は、1つの文字列として1つのデータしか返してくれませんから、あれっ!ということになります。ですから、1つのキーに複数のデータを保存している場合には、この$single の引数には注意が必要ということになります。
ということで、全てのキーの値が1つしかないとわかっているなら、この「取得データ形式」の配列の’single’ の値は必要ありません。引数$single = true で固定してしまえばいいので。逆に全てのデータを$single を指定せず配列で取得して、ということでもいいので、どちらにしても全てのデータを同じ形式で取得するということにすれば、この値は必要ないということになります。
« add_meta_box()による新規セクションの登録 »
投稿の編集画面は「メタボックス」というセクションごとのボックスの組み合わせで構成されていて、独自のセクションを登録する場合にも、まずは新しくこのメタボックスを作成しなければならないということです。しかるにそのメタボックスの作成をする関数が、add_meta_box()で、この関数により記事投稿、ページ投稿、リンク編集画面にセクションを追加することができるということです。
で、その使い方はというと、
パラメータはというと、
$id(必須) | メタボックスの HTML divタグの id 属性値 |
$title(必須) | メタボックスのタイトル、画面上に表示される |
$callback(必須) | メタボックスの内容を表示する(HTML 出力する)関数名 |
$page(必須) | メタボックスの表示先となるページの種類を指定('post', 'page', 'link', またはcustom_post_type。カスタムポストタイプはスラッグを指定) |
$context (オプション) | 編集画面での表示場所 (normal, advanced または side) デフォルトは「advanced」 |
$priority (オプション) | メタボックスが表示される優先度 (high, core, default, low) デフォルトは「default」 |
$callback_args (オプション) | 表示用関数のパラメータを指定(省略時はnull) |
ここのサイトは通常投稿post とカスタム投稿diys でカスタムフィールドを使っているので、それぞれにこの関数が必要になるという事だと思います。ただし、html出力関数は同じものを使い分けることにします。
その、引数$callbackにて指定したhtml出力関数。
6行目のwp_nonce_field()に関してはwordpressのcodexに詳細があります。セキュリティの為のもので、このサイトからの送信であることを確認するためのもの。この部分は参考にさせていただいたサイトの手法をそのまま使わせていただきました。
form の type="text" のinput フィールドは value="" でも空のデータを送信します。データが既存の場合はそれで削除するということでも良いのですが、あえて "checkbox" を設けて(29行目)、空のデータが送信された時は何もせず無視して、"checkbox" にチェックしたときだけデータを削除するということにしました。ちなみに"checkbox" はチェックしなければ送信されません。
« nonce(ノンス) に関して »
wordpressのcodexによるとnonce(ノンス or ナンス)は、
"nonce"はurlとformを悪用から保護するための
"number used once → 一度だけ使用する数字" です。
例えば、管理者ページにおいてポストNo.123を削除するこのようなURLを生成すると、URLの最後に"nonce"を含むことを確認できます。
https://example.com/wp-admin/post.php?post=123&action=trash&_wpnonce=b192fc4204
仮に誰かがポストNo.456を削除するためにURLを修正することを試みたとしても"nonce"は有効ではなく、試みは失敗します。
https://example.com/wp-admin/post.php?post=456&action=trash&_wpnonce=b192fc4204
無効な"nonce"によりwordpressはブラウザに"403 Forbidden"を送信し、"Are you sure you want to do this?"というエラーメッセージを表示させます。
<引用 - wordpress.org codex 訳:この記事の投稿者>
nonceフィールドはフォームの内容が現在のサイトから来たものであり、他のサイトからではないということを認証するために使われます。nonceは完全な保護を提供するものではありませんが、ほとんどの場合は有効な保護になります。フォーム内でnonceフィールドを使うのは重要です。
<引用 - wordpress codex 日本語版>
ということで、これはいわゆるワンタイムチケットということですね。
実は、『続、コメントの編集機能session版』においてsessionを使用したワンタイムチケットを実装したのですが、WordPressにはちゃんとそのための機能が実装されているというわけで、本来ならそれを使えば良かったということなのですね。またしても無知損でした。まぁ、いろいろと勉強になったし、ちゃんと機能しているようなのでそれはそれでいいかと。
< wp_nonce_field() >
実際にそのnonceフィールドを作成してくれる関数がwp_nonce_field()。
パラメータはというと、
$action(optional) | アクション名、optionであるが指定する | 初期値:-1 |
$name(optional) | nonce の名前、optionであるが指定する *nonce にアクセスするにはこの名前を使う→ $_POST[$name] | 初期値:"_wpnonce" |
$referer(optional) | 認証用のrefereフィールドを設定するか否か。 | 初期値:true |
$echo(optional) | hiddenフィールドをフォームに出力するか否か。 falseの場合はPHPの値として返す。 | 初期値:true |
$echoをfalseに$refererをtrueにした場合はwp_referer_field()を使ってリファラーのフィールドを取得する必要があります。$refererをtrueにしnonceフィールドを出力した場合はリファラーフィールドも出力されます。
$actionと$nameはオプションですが、セキュリティを高めたい場合はこの二つのパラメータを設定することを推奨します。パラメータなしで関数を呼び出すのが簡単ですが、nonceがなんのパラメータも必要としなくなってしまうので、デフォルト値が何かを知っているクラッカーにとってあなたのnonceを推測して被害を与えるのが簡単になってしまいます。
<引用 - wordpress codex 日本語版>
ということです。で、実際に出力されるhiddenフィールドはだいたいこんな感じであろうとのこと。
< wp_create_nonce() >
wp_nonce_field()の第一引数、$actionに指定されているwp_create_nonce()。
"nonce"を生成し、リターンする。"nonce"は、現在の時刻、引数$action、およびカレント・ユーザーIDに基づいて生成される。
Parameter $action : Action name. Should give the context to what is taking place. Optional but recommended.
<引用 - wordpress.org codex
パラメータの$action においての説明が私には訳せません。
生成される"nonce"をより推定不能にするために、文字列または数字でユニークな値を指定すべきパラメータということのようです。ちなみにデフォルトは -1 。
私が参考にさせていただいたサイトの方式は、この$action パラメータに現在のファイルのフルパスを表す__FILE__を、nonceの名前に"my_nonce"を指定しているということになります。
< wp_verify_nonce() >
そしてそのnonceが正しく設定されていて制限時間内かどうかを確かめるのがwp_verify_nonce()。
パラメータは、
$nonce(必須) | 認証したいフォーム内で使われたnonce、初期値なし |
$action(optional) | nonceを作成したときに指定したaction名。初期値:-1 |
パラメータ$nonce は送信された$_POST['my_nonce']で得られる値、$action には作成した時のwp_create_nonce(__FILE__)を指定するということになります。
ちなみに戻り値は、認証に失敗すれば false、成功すれば 1 または 2 の整数値で、
- 1:過去12時間内に生成されたnonce
- 2:過去12時間~24時間内に生成されたnonce ということです。
"nonce"に関しては以上で終了。
« 入力した値のデータベースへの保存 »
そして、入力したカスタムフィールド値をデータベースに保存しなければなりません。
投稿が保存される時のアクションフック "save_post" を使います。
html出力関数のところでも書きましたが、データの削除には"checkbox" を別に設けて、それにチェックのある時に実施し、空のデータが送信されてきても何もせず無視するようにしてあります。28行目の$delkeyがそれにあたります。
値の新規登録、変更、削除にはそれぞれWordPressにて用意されている関数を使用します。
空で無いデータが送信され、既存のデータが無い場合に"add_post_meta()" で新規データを登録していますが、これはわざわざ分岐させなくても"update_post_meta()" がやってくれるのでは、とどこかに書いてあったような気もしますが。
$post_id(必須) | カスタムフィールドを追加する投稿の ID |
$meta_key(必須) | カスタムフィールドのキー |
$meta_value(必須) | カスタムフィールドの値 |
$unique(optional) | キーをユニークにするかどうか。true のときは、指定した投稿に $meta_key を持つカスタムフィールドが無いときのみ追加し、すでにカスタムフィールドが存在していれば追加されません。 |
$post_id(必須) | 削除したいカスタムフィールドを持つ投稿の ID |
$key(必須) | 削除したいカスタムフィールドのキー |
$value(optional) | 削除したいカスタムフィールドの値。これは、同じキーを持つカスタムフィールドを区別するパラメータです。省略すると、指定したキーを持つカスタムフィールドはすべて削除されます。 |
$post_id(必須) | カスタムフィールドを持つ投稿の ID |
$meta_key(必須) | 更新したいカスタムフィールドのキー |
$meta_value(必須) | カスタムフィールドの新しい値 |
$prev_value(optional) | 更新したいカスタムフィールドの元の値。これは、同じキーを持つカスタムフィールドを区別するパラメータです。省略すると、指定したキーを持つカスタムフィールドはすべて値が更新されます。 |
これで投稿入力フォームにカスタムフィールドの入力フォームを表示することが出来たのですが、テストをしながらデータベースを見ていてちょっと気が付いたことがあります。
というのは、カスタムフィールドの値を保存しているデータベースのテーブルはwp_postmetaテーブルになるのですが、post_idフィールドの値が変更した投稿のpostIDの値で、フィールドmeta_valueがそれぞれ同じく1で、フィールドmeta_keyの値が_pingmeと_encloseme という二つのレコードが同時に追加されているようでした。
同じ投稿で変更を何度か行うと、その都度この二つのレコードが追加されて増えて行くようです。他にもpost_idフィールドに同じpostIDの値をもつレコードはあって、そのmeta_keyの値は_edit_last と_edit_lock の二つあるのですが、これらはなんとなく存在意味がわかるようですし、重複して増えていくことはありません。
さて、このmeta_keyの値が_pingmeと_encloseme というレコードは何のために作成されているのかというのがとても気になるところなのですが、日本語のページにおいてそれらの情報は見つけられませんでした。英語のサポートには若干あって、これがまたあまりわからないことなのですが、それによるとwp-cron によっていつか実行されるであろう処理の対象の目印として作成されているもので、処理が済めば自動的に削除されるであろうとのこと。
そもそもwp-cron がまったく接触したことのない未知の領域なのでさっぱりわかりません。
ためしに、ここで造った機能を無効にして、再びプラグインを起動させてやってみたところ結果は同じ。プラグインの内部を確認してみるとデータの変更には同じくupdate_post_meta() を使っていたのでそれもそのはず。いっそのことwordpress で用意されている関数を使わずに、sql で直接データを処理しようかとも思ったのですが、まぁ、wordpress が行っていることだし、いずれ自動的に削除されるということなのであまり気にせずにいたほうが良いように思いました。
Post : 2014/11/05 00:47
Comments feed
Trackback URL : https://strix.main.jp/wp-trackback.php?p=48172