Advanced Custom Fields を使ってカスタマイズする際、メタキーだけでなく、内部的に使われるキー(field_xxxxxxxという名前になっている)が欲しい時がある。
さてそのkeyをどうやって知るのだろうか?
ドキュメントを見てもそのような関数はなさそうだ(get_key()みたいな)
そこで自分は以下のコードを使って、全部のフィールド名とキーを対にしたデータを吐き出し、使っている。
/* ACFフィールド名を得る */ function get_field_names($name){ $fg = get_posts(array('name'=>'acf_'.$name , 'post_type'=>'acf')); $cf = array(); $fgmeta = get_post_meta($fg[0]->ID); foreach($fgmeta as $key => $field) { if(substr($key, 0, 6) == 'field_') { $field = unserialize($field[0]); $cf[$field['name']] = $field['key']; } } return $cf; }
その後の考察
気になってACFのデータをちょっと解析してみたところ、いろいろ誤解していたことが分かった。
これまでは「ACFのnameはpostmetaのキーではなく、実際は内部キーを使っている」と信じ込んでいたが、まず、単一データのフィールドの場合(おそらく複数データでも同じ)ACFのフィールド名はやはりそのまま、postmetaのkeyに該当する。なのでget_post_meta()もマジックメソッド$post->hogeも使えるはず。
では、ネイティブ名である「field_xxxxxxxxx」は一体どういう役割を持つのか?
まず。例えばキーはmykeyだとするとpostmetaには
meta_key => ‘_mykey’
meta_value => ”fieldxxxxxxxxx’
と入ってくる。つまりキーとネイティブ名の対応を示している。update_field()を使用するこれがセットされる。なのでupdate_post_meta()を使うとこれがセットされず、おそらく管理画面には反映されない。
※この行を削除しても管理画面には反映されることを確認。おそらく繰り返しフィールドなど複雑なデータで生きてくるのだろう。
先日書いた保存ルーチンでは、この対応関係に整合性が取れなくなり複数のフィールドに同じ値が入っていくという珍現象が起きてしまった。
とりあえず、保存はともかく読み出しにはget_post_meta()が使えるということでひとまず安心した。
後日談———————————–
get_field()
update_field()
この二つがどうも曲者で、なぜか特定のフィールドだけ保存・読み出しができないということが判明した。
従来通り
get_post_meta()
update_post_meta()
を使えば問題はなく、管理画面へも反映される。ただこの場合fieldxxxxxxxというキーとの紐付けが行われず、いずれ不具合が起こる可能も出てくる。
そういうこともあり、自作部分が多い場合ACFの使用を避けたい。問題はクライアントが納得するかどうか。
もうひとつ、テキストエリアでget_field()を使用時に、勝手に<br />を挿入されてしまう現象があった。おそらく内部でnl2brが行われている模様。これはフィールド設定時に変更できると思うが要注意。
出力時はget_field、フォームの規定値にはget_post_metaを使うべし。
後日談part2———————————–
ACFのフォームと自前フォームを混在させる場合、注意しなければいけない点がある。
ご存知のようにACFは複数の値を持つカスタムフィールドを保存する場合、配列として保存する。ここがいつも問題になるところだ。なので、取り出すときはget_post_meta()の第3パラーメータはtrueだ。
ここで、ひとつの値を持つチェックボックスを付けた時にハマった。
自前フォームの場合、仮にkeyを’check’、valueを’yes’とした場合、stringの’yes’ が保存され、出てくる。
なぜならば、inputのnameにブラケットを不要と思ってつけなかったので、普通に単独の値として処理された。
ところがACFで同じ項目を保存したら
array([0] => ‘yes’)
と出てくるではないか。チェックボックスは問答無用でarrayにされてしまうのだ。
これが誤動作を起こした。
解決策としては、自前フォームでもnameにブラケットをつけて、arrayで保存する。hiddenを設置してチェックしなかった場合の値を送りたい時(常套手段ですね)も、ブラケットをつける。
自作フォームヘルパーを使っていたので、自然にブラケットが外れてしまっていた。(というか付けない仕様にしていた。単独選択なら必要ないですね)
自分は保存ルーチンで強制的にarrayで保存するようにした(ダーティ)
結論:ACFは色々大変。独自世界を行ってる。
コメント