はじめに
WordPressはサイト全体を投稿本文のように編集できる「ブロックテーマ」に本格的に移行しています。
多くの資料がありますが、カスタムフィールド(投稿メタ)の表示に関する情報が少ないです。
現実には、画像のようなゴリッゴリのカスタムフィールドを多用したサイトを運用していて、頭を抱えている人も多いのではないかと思います。そのような人の一助となれば幸いです。
カスタムフィールドを表示することは、できます。
が、この記事を書いている時点では難易度が高めです。また、仕様が変わる可能性も高いです。
読んでいるあなたがWordPressについて常時学習する時間が取れない、納品後の改修ができない状況であれば、他のCMSへの乗り換えを強く勧めます。
暫定措置
ノーコードで表示する
「Snow Monkey Blocks」プラグインには、カスタムフィールドの内容を表示できるブロックがあります。
ただし表示できるのは文字列だけで、画像カスタムフィールドは画像IDが表示されてしまうため使用できません。出力されるコードはdiv要素となります。
<div class="smb-custom-field wp-block-snow-monkey-blocks-custom-field">
カスタムフィールドに入力した情報
</div>
旧来のコードのまま表示する
「Custom Blocks Constructor – Lazy Blocks」は、旧来のWordPressのテーマのコードからブロックを作成できます。
Block Bindings APIを使用する
ここからは今後のWordPressの推薦、「ブロックバインディングAPI」を使用する方法の解説です。バージョン6.6を使用している前提です。
お急ぎの方は4.まで飛ばすことができますが、おそらく後悔します。
1. Block Bindings APIとは
テンプレートに書いてあるブロックに外部情報を関連付けて、置き換えられる機能です。例として以下のようなことができます。
- クエリループ内の投稿テンプレートや、各記事に配置したブロックの…
- 段落を、投稿内のカスタムフィールドに登録した文字で置き換える
- 画像のURLを、投稿内のカスタムフィールドにアップロードした画像のURLで置き換える
- ボタンのリンク先を、投稿内のカスタムフィールドに登録したURLで置き換える
2. 置き換えられる値の制限
記事を書いている時点で、置き換えができるブロックは画像、段落、見出し、ボタンに制限されています。また、見出しと段落以外は全体のHTMLを置き換えることはできません。つまり、投稿ループ全体をa要素で囲むなど、大幅な加工はできません。
詳細は以下を参照ください。
例えば画像は、以下の3つの属性値のみ可能です。
- 画像のURL
url
- 画像の代替テキスト
alt
- 画像のタイトル
title
このため、SEOやスライドショーで表示するために、altやtitleも書き換えたい場合は、関連付けをこれらにも行わなくてはなりません。この記事ではURLの差し替えのみ解説します。
3. ACFに関する注意
Advanced Custom Fields(以降、ACF)プラグインはWordPress公式のカスタムフィールドとは規格が異なるので、後述の core/post-meta
では表示できません。また、ブロックエディタ内では表示を確認できません。
「6. 画像ブロックを置き換える関数を追加する」の解説は、WordPress公式のカスタムフィールド前提で解説しています。もしかするとACFの画像ブロックだともっと簡単に表示できるかもしれません。この記事を書いている時点で未検証です。すみません。
以降、文字、画像のバインディングを解説していきます。
4. カスタムフィールドをブロックが参照できるようにする
ACFでカスタムフィールドを作成している場合は、この作業は不要なので飛ばしてください。
現在使用しているテーマの functions.php
にコードを追記して、ブロックに関連付けたいカスタムフィールドを登録してください。
以下のサンプルコードでは投稿タイプ sightseeing
に、カスタムフィールド sightseeing_catch, sightseeing_thumbnail
を関連付けています。
add_action( 'init', 'mysite_register_post_meta' );
if ( ! function_exists( 'mysite_register_post_meta' ) ) {
function mysite_register_post_meta() {
register_post_meta(
'sightseeing',
'sightseeing_catch',
array(
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
'single' => true
)
);
register_post_meta(
'sightseeing',
'sightseeing_thumbnail',
array(
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
'single' => false
)
);
}
}
- 以降、
mysite
はテーマ名などに置き換えてください - この作業は、将来のバージョンアップで不要になってくれればいいなあと期待しています
入力データの無害化 sanitize_callback
はこちらの記事が詳しいです。
5. 文字列フィールドを表示する
画像を置き換えたい場合は、この項は飛ばしてください。
表示したいテンプレートの編集画面へ移動し、右側の詳細メニューから「コードエディター」に切り替えます。
(実はテーマのテンプレートHTMLを直接編集する手もありますが、ここでは割愛します)
カスタムフィールドを表示したい段落ブロックを探します。
以下のようになっているはずなので
<!-- wp:paragraph -->
<p>これはキャッチコピー</p>
<!-- /wp:paragraph -->
開始タグを以下の通り書き換えてください。 サンプルコードでは key
にさっき関連付けたカスタムフィールド名 sightseeing_catch
を指定しています。
<!-- wp:paragraph {
"metadata":{
"bindings":{
"content":{
"source":"core/post-meta",
"args":{
"key":"sightseeing_catch"
}
}
}
}
} -->
ACFの場合は source
の値を以下の通り acf/field
としてください。
<!-- wp:paragraph {
"metadata":{
"bindings":{
"content":{
"source":"acf/field",
"args":{
"key":"sightseeing_catch"
}
}
}
}
} -->
編集後、コードエディタを閉じると、段落ブロックが編集できなくなり、文字列がカスタムフィールドに置き換わっているはずです。
6. 画像ブロックを置き換える関数を追加する(前半)
現在使用しているテーマの functions.php
に以下のコードを追記してください。
register_block_bindings_source
の第一引数 mysite/image
は控えておいてください。
add_action( 'init', 'mysite_register_block_bindings' );
function mysite_register_block_bindings() {
register_block_bindings_source( 'mysite/image', array(
'label' => 'mysite_image',
'get_value_callback' => 'mysite_image_binding',
'uses_context' => [ 'postId' ]
) );
}
register_block_bindings_source
関数
ブロックの source
に第一引数の文字列が指定されていたときだけ、第二引数の get_value_callback
の値の名前の関数を実行します。 uses_context
で、その関数に投稿のIDを渡しています。
実行関数 mysite_image_binding
が必要になることがわかります。
7. 画像ブロックを置き換える関数を追加する(後半)
続けて以下のコードを追記してください。 $image_src
には画像がなかったときのノーイメージのURLを記述してください。
function mysite_image_binding( $source_args, $block_instance ) {
$image_src = 'https://mydomain/path-to-theme/noimage.png';
if($block_instance->context['postId'] && $source_args['key']) {
$image_src = wp_get_attachment_image_url( get_post_meta( $block_instance->context['postId'], $source_args['key'], true ), 'large' );
}
return esc_url($image_src);
}
ここでは、カスタムフィールドの画像URLを取得しています。最終行の return
の値がブロックに置き換える内容となります。
8. 画像ブロックを表示する
表示したいテンプレートの編集画面へ移動し、右側の詳細メニューから「コードエディター」に切り替えます。
カスタムフィールドを表示したい画像ブロックを探します。
開始タグが以下のようになっているはずなので
<!-- wp:image {(ブロックの設定値が書かれている)} -->
以下の通り書き換えてください。 サンプルコードでは source
に控えておいたregister_block_bindings_source
の第一引数 mysite/image
、 key
にさっき関連付けたカスタムフィールド名 sightseeing_thumbnail
を指定しています。
<!-- wp:image {
"metadata":{
"bindings":{
"url":{
"source":"mysite/image",
"args":{
"key":"sightseeing_thumbnail"
}
}
}
},
(ブロックの設定値が書かれている)
} -->
編集後、コードエディタを閉じると、画像ブロックが編集できなくなり、公開画面の画像がカスタムフィールドに置き換わっているはずです。
「7. 画像ブロックを置き換える関数を追加する(後半)」で、 $source_args['key']
という変数が出てきました。実はここには、ブロックの key
で指定したカスタムフィールド名が渡されています。
投稿IDとカスタムフィールド名を参照して、画像のURLを取得して置き換える、という仕組みです。
おわりに
WordPressのブロックテーマで、各投稿のカスタムフィールドを表示する手順は以上です。繰り返しますが、この記事の内容も古い or 間違いがあるかもしれません。コメントでご指摘いただけますと幸いです。
他にもよくあるカスタマイズとして、「カスタムフィールドに入力したURLをボタンのリンク先にする」がありますが、画像フィールドと同じ手順で実装できるので割愛しました。
なお、本文の特定のブロックのHTMLを、一覧ページにそのまま表示することも可能です。記事を書いている時点では、やや魔改造じみたカスタマイズになりますが、今後のバージョンアップによっては、クエリループの検索条件に使用しないカスタムフィールドは不要となるかもしれません。
謝辞
この記事は下記を始めとした、多数のドキュメントを参考にさせていただきました。