WordPressのブロックをテンプレートの任意の位置に振り分けて表示する方法

WordPressのクラシックテーマで制作しているWebサイトにおいて、1ページの中でブロックの表示位置を振り分ける方法について紹介しています。

テンプレートの任意の位置にGutenbergブロックを呼び出せるため、カスタムフィールドの代わりにブロックでコンテンツを管理したい場合に有効な方法です。

どのようなケースか

次の画像はカスタムブロックを2箇所に挿入したページです。

カスタムブロックを2箇所に挿入したページ

背景色グレーのセクションが3つあり、最初のセクションに「ブロックA」を、最後のセクションに「ブロックB」のカスタムブロック(黒背景に白文字のテキスト)を挿入しています。カスタムブロック以外のHTMLは全てテンプレートに直接記述しています。

エディタでは次のようになっています。2つのブロックを挿入しただけのシンプルな画面です。

カスタムブロックを2箇所に挿入したページの編集画面

この方法は、ページ全体はテンプレートで構成しつつ、特定のセクションのみ編集可能にしたい場合に有効です。企業サイトを例にすると以下のようなイメージです。

ページ内コンテンツの例
- 企業情報 ← 固定
- 実績 ← ブロックを活用したい
- サービス内容 ← 固定
- お客様の声 ← ブロックを活用したい
- お問い合わせ ← 固定

本文を表示する<?php the_content(); ?>では、ブロックをセクションごとに分割して表示することは困難です。そこで今回の方法の出番となります。

動的に変更したい箇所が複数ある場合、カスタムフィールドを使うケースも多いかと思いますが、ブロックで管理したい場合や繰り返しフィールドが使えない環境では、この方法が有効な選択肢になり得ます。

実装例

早速ですが以下が実装に使用したコードです。

functions.php
/**
* 指定したブロック名のブロックだけを出力するヘルパー関数
*
* @param array $blocks parse_blocks()で得られるブロック配列
* @param string $block_name 抽出したいブロック名(例: 'lazyblock/block-a')
*
* @return void
*/
function render_blocks_by_name($blocks, $block_name) {
foreach ($blocks as $block) {
if ($block['blockName'] === $block_name) {
echo render_block($block);
}
}
}
page.phpなど
<?php
$content = get_the_content();
$blocks = parse_blocks($content);
?>
<section>
<h2>見出し</h2>
<?php render_blocks_by_name($blocks, 'lazyblock/block-a'); ?>
</section>
<section>
<h2>見出し</h2>
<p>テキストが入ります。テキストが入ります。テキストが入ります。</p>
</section>
<section>
<h2>見出し</h2>
<?php render_blocks_by_name($blocks, 'lazyblock/block-b'); ?>
</section>

ヘルパー関数をfunctions.phpで定義し、テンプレート側でその関数を呼び出しています。コードのポイントを順に説明します。

ブロックデータの取得

テンプレートの冒頭でget_the_content()で投稿本文を取得し、parse_blocks()でブロック構造の配列に変換しています。この処理は1回のみ行い、以降は変数$blocksを使い回します。

ブロックの出力

render_blocks_by_name()関数は、$blocksの中から引数で指定したブロック名(例:lazyblock/block-a)と一致するブロックを抽出し、render_block()でHTMLとして出力します。テンプレートの表示したい箇所でこの関数を呼び出すだけで、対象のブロックを任意の位置に配置できます。

今回はLazy Blocksのカスタムブロックを使用していますが、コアブロックでも同様に機能します。

動作確認環境

以下の環境において動作を確認しました。

  • WordPress 6.9.4(クラシックテーマ)
  • PHP 8.0.0
  • Lazy Blocks 4.2.1

注意点

実装時の注意点を以下にまとめます。

ブロックが挿入されていない場合

エディタに対象のブロックが挿入されていない場合、foreach内の条件に一致しないため何も出力されません。エラーは発生しませんが、必須のコンテンツであればフォールバックを用意しておくと安全でしょう。

同じブロックが複数挿入されている場合

同じblockNameのブロックが複数挿入されている場合は、すべてが同じ位置に出力されます。1つだけ表示したい場合はループ内でbreakを追加するなどの対応が必要です。

この方法のメリット・デメリット

メリットとデメリットをまとめると次のようになります。

メリットデメリット
  • テンプレートの任意の場所に任意のブロックを挿入できる
  • レイアウトを固定できるため、編集ミスでレイアウトが崩れない
  • HTMLを綺麗に保てる(不要なラッパーを排除できる)
  • カスタムフィールドライクにカスタムブロックを使用できる
  • エディタとフロントの見た目が乖離する
  • 編集画面から自由にレイアウトをコントロールできない
  • ブロックを「データソース」として扱うため、ブロックでレイアウトまで管理するというWordPressの設計思想とはズレがある

今回の方法は、ブロックを「レイアウト要素」ではなく「コンテンツデータ」として扱う設計とも言えます。

カスタムフィールドとの比較

冒頭でも触れましたが、カスタムフィールドの繰り返し機能を使用できない現場ではかなり有効な方法だと感じています。両者を比較すると次のようになります。

観点カスタムフィールド(ACF等)今回の方法(parse_blocks)
データの保存先postmetapost_content(投稿本文)
編集UIフィールド専用のフォームブロックエディタ
コンテンツの自由度フィールドの型に依存するブロックで表現できる範囲で自由
繰り返しコンテンツ繰り返しフィールド(Pro / 有料)ブロックの追加で対応可能
導入コストフィールド定義+テンプレート実装ブロック追加+テンプレート実装
エディタの見た目フォーム形式(実際の表示とは異なる)ブロックの実装による(Lazy Blocks無料版の場合はフォーム形式)
プラグイン依存Advanced Custom Fields等が必要ブロック作成にLazy Blocks等が必要(コアブロックのみなら不要)

まとめ

parse_blocks()render_block()を組み合わせることで、クラシックテーマのテンプレート内の任意の位置にブロックを表示することができました。ブロックの編集体験を活かしたい際に有効な方法です。

デメリットを把握したうえで適切な場面で使用していきたいです。

この記事を書いた人

写真:ブール 代表 西川雅人

Masato Nishikawa

ウェブ制作会社・デザイナー様向けに、コーディングやWordPress実装を承っているフリーランスです。繁忙期のサポートや、継続的な外注先をお探しでしたら、お気軽にお声がけください。

コーディングや
WordPress実装の
ご相談を承っています。

新規制作から運用フェーズの修正まで柔軟に対応します。
お見積りや実装可否の確認など、お気軽にご連絡ください。