Advanced Custom Fieldsのupdate_fieldとfield_key

Advanced Custom Fieldsという人気のプラグインがあります。WordPressのカスタムフィールドをリッチに・多機能にしてくれるプラグインです。有効化済みインストールが100万以上でレイティングも5点満点中4.9という凄いプラグインです。

https://ja.wordpress.org/plugins/advanced-custom-fields/

使ってる人も多いので検索すると日本語の記事もかなりヒットするのですが、今回APIを触っていて少しハマったのでメモとして残しておきたいと思います。

フィールドを更新するupdate_field

Advanced Custom FieldsのAPIでget_fieldというものがあります。そのままですが、カスタムフィールドの情報を取得するAPIです。

$field = get_field($field_name, $post_id, $format_value);

$field_nameは自分がAdvanced Custom Fieldsの画面で定義したフィールド名です。

これと対になるのがupdate_fieldです。update_fieldのAPI仕様はこちらになります。

update_field($field_key, $value, $post_id)

上記をよく見ると$field_keyと書いてあってここがハマりどころです。実はget_fieldと同じようにfield_nameを渡しても更新が出来てしまうのですが動作が少し微妙です。

API仕様を読んだら普通に書いてあるんですけどね…。

So when can I use $field_name?

If the reference for a value already exists, you can use the $field_name as the first parameter in the update_field function. ACF will lookup the field reference / field object from that field name.

referenceが存在しない時には呼ぶべきではないという事で、おそらく新規に投稿作成時などではfield_keyを使って呼ぶのが正しい手順になります。

update_fieldでfield_nameを渡すとどうなる?

ただ、実は新規投稿作成時にfield_nameを渡してもカスタムフィールドの値を更新できます。たとえばAPIで投稿を作成しupdate_fieldを使って更新した場合、その後投稿の編集画面から意図した値が入っていることを確認できました。ただし、編集画面からその投稿を自分で公開したり更新しないとget_fieldで値を取得する事ができませんget_fieldの戻り値がnullなど無効な値になります。

なまじ値が入ってくれたりするので、今回気づくのに遅れました。publish状態で投稿を作った際に手動では公開や更新などをしていないのでget_fieldを呼んだら画面に何も表示されてなくてハマったというわけです。

じゃあfield_keyとは何だ?

ではfield_keyとは何なんでしょう?このfield_keyは少し分かりにくいんですが、Advanced Custom Fieldsのカスタムフィールドの定義画面で確認する事ができます。デフォルトだと表示オプションで無効になってるので表示されてませんが。下記のようにShow Field Keyを有効にすると出てきます。分かりにくい!

NewImage

この出てきた乱数っぽいやつをupdate_fieldに指定する必要があるというわけですね。Advanced Custom Fieldsはすごく良く出来てるプラグインなのですが、これはちょっと分かりにくなーと思いました。

field_nameからfield_keyを取得する

ただ、この乱数のようなfield_keyをハードコーディングする事は避けたいです。それで、どうしたかというと下記のようにコーディングしてfield_nameからfield_keyを取得するようにしました。

// acfの定義情報を取得する
$acf_posts = get_posts( [ 'post_type' => 'acf' ] );
$acf_defs = apply_filters( 'acf/field_group/get_fields', [], $acf_posts[0]->ID );

// 定義情報から field_name で該当する定義情報を引当て field_key を取得する
$idx = array_search( $field_name, array_column( $acf_defs, 'name' ) );
$acf_field_key = $acf_defs[ $idx ]['key'];

// field_key で更新する
update_field( $acf_field_key, $val, $post->ID );

これでたとえば投稿の作成からカスタムフィールドの更新までをAPIで行ってもget_field等が正常に動作します。

しかしドキュメントを読んでないぼくも悪いんですが、このfield_keyの仕様どうにかならないですかね。それにこのfield_keyの取得方法についても分かりにくく、海外のポストを見てるとSQLを発行して取得してる例もありました。上記の方法がベストかは分からないですが、お試し下さい。本来は取得できるAPIが用意されていても良いのにな…。