検索キーワードを入力
カテゴリーを選択

初心者必見!WordPressのブロックを自作する方法を徹底解説(PHP,React.js)+サンプルコード付き

投稿日:2025年07月20日(日)
初心者必見!WordPressのブロックを自作する方法を徹底解説(PHP,React.js)+サンプルコード付き|UMENOKI|すぐに仕事で使えるIT技術情報メディア

みなさんこんにちは!エンジニアの高澤です!

今回は、WordPressのブロックを自作する方法を徹底解説したいと思います。

WordPressのブロックは、すでにWordPressをインストールした時からデフォルトで多数のブロックが用意されておりますが、WordPressでサイトを運営するユーザーによっては「こういうページを作りたいけど欲しいブロックがない…」だったり、「こんなブロックが欲しいなぁ…」といったように、なかなか欲しいブロックがなかったりして困ることがあります。

そんな時に当記事の内容が役に立ちます!

当記事では、WordPressの公式ドキュメントのブロック開発のチュートリアルを参考にしつつ、当記事独自の切り口でさらにわかりやすくして初心者でも無理なくブロック開発ができるように記事の内容を構成しております。

よろしければぜひ当記事の内容をテーマ開発やプラグイン開発、またWebサイト制作で開発などのお仕事でご活用いただけましたら幸いです。

目次

WordPressのブロックとは

WordPressのブロックとは、投稿ページ(記事)や固定ページの内容を構成するパーツのことを言います。

ブロックは、ブロックエディタ(Gutenberg:グーテンベルク)にて使用できる機能になります。

例えば、段落の文章や画像、見出し、ボタンなどのページに必要なパーツをそれぞれブロックという単位で扱うことができ、ブロックエディタ上で自由自在に配置して設定することができます。

今や現代的で最新の機能を搭載さいているモダンなCMSであれば、このビジュアルを通して直感的にページのパーツを配置して

例えば、筆者が知る限りではHubSpot(ハブスポット)が提供するCMSが似たようなエディタの機能を搭載されているかと思います。

ちなみにブロックエディタの基本(UIの名称等)について詳しく知りたい方は以下の公式マニュアルをご確認ください。

WordPressブロックのメリット

WordPressのブロックのメリットと、WordPressのブロックを自作できるメリットの2点について解説したいと思います。

それぞれ解説いたします。

WordPressブロックのメリット

まずWordPressのブロックのメリットということで解説いたします。

WordPressのブロックのメリットとしては、ページの作成者、記事の執筆者がエディタを通して視覚的にわかりやすくパーツを配置したり編集したりできるところかと思います。

つまり、かなり直感的にパーツを配置したり編集したりできます。

ブロックであれば、ページに表示される内容がそのままエディタで確認できるため、WordPressでブログを始めたばかりの初心者でも簡単にページを編集することが可能です。

また、ブロックであればショートコードや旧クラシックエディタと比べたら自由度が非常に高く、ご自身のサイトに合わせて自由自在にデザインなどを編集することが可能です。

下図のように、ブロックには画面右側に設定パネルという機能があり、設定パネルにある項目の内容を変更することでブロックの表示をカスタマイズすることができます。

もうこれだけでもメリットはお分かりいただけたでしょうか?

こんな感じで、WordPressのブロックを使えば初心者でも簡単にリッチなページを作成できるため、ブロックエディタを利用いただくことに価値があるのではないかと思います。

WordPressブロックを自作できるメリット

次にWordPressのブロックを自作できるメリットについて解説いたします。

それはなんといっても「こんなブロックが欲しい…」という要望に応えられるということだと思います。

WordPressがデフォルトで提供しているブロックは多数ありますが、なかなか痒いところに手が届かないというか、こうしたいのにできない…といった具合にどうしてもやりたいことができなかったりする場合があります。

そんな時に自作でブロック開発ができると、そのユーザーの欲しいブロックを要望に応えつつ作成することができます。

WordPressブロックを自作で開発する方法

それでは早速、ブロックを自作で作成する方法について解説いたします。

エンジニアリング的に全くの初心者の方は事前に必要なスキルが多かったりして色々確認する必要がありますが、結果的にブロックが作れるようになるのでそこは頑張りましょう。笑

ちなみに当記事では以下のWordPress公式のチュートリアルページを参考に解説いたしますので、気になる方や進めてみてうまくいかない方はこちらをご確認ください。

当記事と実際の公式チュートリアルページを二重でご確認いただくことで、より理解が深まることと思います。ぜひご活用ください。

それではブロックを楽しく作っていきましょう!

WordPressブロック開発に必要なスキル

まず事前にWordPressブロック開発に必要なスキルについてお伝えしておこうと思います。

ブロック開発にはそれなりにスキルが必要で、例えば以下のような技術がわかっていなければブロックを自作することはできません。

以下の表をご確認いただき、ご自身が事前に確認しておくべき技術や知識を把握しておきましょう。

スキル説明
HTMLブロックの構造を作るための基本スキル。
CSSブロックの見た目を整えるスタイル指定。
JavaScript (ES6以上)ブロックの動作を定義する中心技術。GutenbergはReactベースなので重要。
ReactGutenbergはReactで構成されているため、コンポーネントやJSXの理解が必要。
WordPressのブロックエディターAPIregisterBlockType()関数などのブロック登録用APIなどの、WordPressが提供するブロック開発周りのAPI等の理解。
npm / Node.js開発環境構築やビルドに使用。パッケージ管理にも使う。
Webpack / BabelGutenberg開発用のビルドツール(WordPressが推奨する開発構成に含まれる)。

当記事で作成するブロック

当記事では、コピーライト表示のブロックのプラグイン(コピーライトブロック)を作ります。

コピーライトとは、Webサイトのフッター付近によくある下図のやつですね。

そしてブロックのイメージとしては下図のようなブロックです。

画面左のインサーターには「Copyright Date Block」というアイコンが追加され、クリックするとコンテンツキャンバスに自作したコピーライトブロックが追加され、そのブロックをコンテンツキャンバス上でクリックすると、画面右の設定パネルにてブロックを編集できるUIを追加いたします。

ちなみに現時点でブロックエディタ上の動きを確認したい方は、以下のURLにてデモを利用することができます。気になる方はぜひ確認してみてください。

https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/WordPress/block-development-examples/trunk/plugins/copyright-date-block-09aac3/_playground/blueprint.json

WordPressブロック開発に必要なツール

まずブロック開発には必要なツールがありますのでここで事前に整理しておきたいと思います。

結論としては、まず以下のツールが必要になります。

  • コードエディタ(Visual Studio Codeなど)
  • ターミナル(コマンドプロンプト)
  • Node.jsとnpm
  • ローカルのWordPress環境(Dockerなど)

それぞれ順番に解説いたします。

コードエディタ(Visual Studio Codeなど)

まずコードエディタというエンジニアにとっては必須のソースコードを編集するためのツールを、ご自身のPCへインストールしましょう。

筆者のおすすめはVisual Studio Codeです。
理由は何より無料で、高機能なエディタ機能を提供してくれるからです。

また、コードエディタはまだまだ様々なものが提供されておりますが、Visual Studio Codeは世界共通でほぼスタンダードなコードエディタといっても過言ではないかと思います。

こちらからダウンロードできるので、そもそも迷っている方やコードエディタをPCにインストールされていない方は試しにでもご利用ください。

https://code.visualstudio.com/Download

ターミナル(コマンドプロンプト)

ターミナル(Terminal)、またはコマンドプロンプト(Command Prompt) とは、コンピューターに文字(コマンド)だけでPCに命令を与えることができるアプリケーションのことを言います。

通常PC利用時は、パソコンをマウスやタッチ操作で使いますが、ターミナルなどを利用すれば、キーボードからコマンド(命令文)を打ち込んで操作できます。

ターミナルはMacやLinuxで主に使われ、コマンドプロンプトはWindowsに標準搭載されているターミナルの一種になります。

筆者はMacbook Proを利用しているため、Macを前提に話を進めていきますが、Windowsをご利用になっていても参考になりますのでご安心ください。

ターミナルは作業時にめちゃくちゃ使うので、ここで立ち上げておきましょう。Macにて以下のアイコンがあるかと思いますので、クリックしましょう。

クリックすると下図の様にターミナルが立ち上がります。

今後は、このターミナルから様々なコマンドを実行して、タスクを処理していきます。

Node.jsとnpm

次にNode.jsとnpmをご自身のPCに用意します。

Node.js(ノードジェイエス) とは、JavaScriptを「ブラウザの外」で動かすためのプログラム環境です。

通常JavaScriptはWebページなどブラウザの中だけで動きますが、Node.js を使うと、JavaScriptをパソコンやサーバーの上でも実行できるようになります。

例えば、次のようなことができます。

  • サーバーを立ち上げる(Webアプリの裏側を作る)
  • ファイルを読み書きする
  • 自動処理(ビルドやテスト)を行う
  • CLIツール(コマンドラインアプリ)を作る

npm(エヌピーエム) とは、Node.js用のパッケージ管理ツールのことを言います。

簡単に言うと、必要なライブラリやツールをコマンドでインストールする仕組みです。

例えば、以下のようにターミナルからコマンドを書いて実行するだけで、Reactというライブラリを簡単にプロジェクトに追加できます。(以下のコマンドは当記事では使用しません)

npm install react

やり方に関しては、Homebrewも含めて以下の記事にてセットアップ方法を詳しく解説しておりますので、よろしければご活用ください。

ローカルのWordPress環境(Dockerなど)

プラグインやテーマ開発を行う際は、PCのローカル環境にWordPress環境がなければ始まりません。

当記事では、WordPressのローカル環境を手軽に作成できるツールであるwp-envを前提にブロック開発の話を進めていきたいと思います。

wp-envについてピンとこない方は、以下の公式ドキュメントにて詳しく解説しておりますので、よろしければご活用ください。

また、wp-envでのWordPressのローカル環境の立ち上げ方に関しては、以下の記事にて詳しく解説しておりますのでよろしければご活用ください。

ちなみに当記事では説明上「wp_block_dev」という名前のディレクトリでwp-env(Docker)を利用することを前提に解説いたします。

wp-envのセットアップができたら、Docker(Docker Desktop)は起動しておいてください。

WordPressブロックのひな型の作成

ここまでで、ブロック開発に必要なツールや開発環境がひと通り準備できた状態かと思います。

ブロック開発において、まず最初に@wordpress/create-blockというブロックの開発のベースとなるひな形を簡単に作ることができるパッケージを利用して、サンプルブロックを作ります。

開発方法をざっくりいうと、この@wordpress/create-blockで作成したサンプルブロックをカスタマイズする形でブロックを作っていくことになります。

それでは早速作っていきましょう。下図のようにまずターミナルを開いてください。

ターミナルを開いたら、以下のコマンドを参考にwp-envでデスクトップへ作成したローカル環境のディレクトリへ移動してください。

// デスクトップへ移動
cd desktop

// wp-envでデスクトップへ作成したローカル環境のディレクトリへ移動(※「wp_block_dev」のディレクトリ名はご自身で作成されたディレクトリ名に変換してください)
cd wp_block_dev

上記コマンドの「wp_block_dev」のディレクトリ名はご自身で作成されたディレクトリ名に変換してください。

移動できたら、以下のコマンドを実行してwp-env(Docker)を起動しましょう。うまくいかない方は今一度こちらの記事をご確認ください。

// wp-envを起動
npx wp-env start

これでご自身のローカル環境にWordPressを起動することができたかと思います。

WordPressのローカル環境が作れたら、@wordpress/create-blockでブロックのプラグイン(ひな形)を作ります。

以下のコマンドを実行してください。

npx @wordpress/create-block@latest copyright-date-block --variant=dynamic

すると下図のように実行結果が表示されるかと思います。「Ok to proceed? (y) 」と問われるので「y」と入力して実行してください。

すると下図のように処理が実行されて、処理が完了するかと思います。

完了後、下図のように「copyright-date-block」というファイルが作成されているかと思います。

ファイルの中身を確認すると、見事にブロックのひな形であるサンプルのブロックプラグインが作成できているかと思います。

作成できたら、次はwp-envの隠しファイルである.wp-env.jsonファイルに今作成したサンプルプラグインをローカル環境のWordPressに登録していきたいと思います。

.wp-env.jsonは隠しファイルなので、Macをお使いの方はshift+command+.のショートカットキーで隠しファイルを表示させてください。

.wp-env.jsonを開いたら、以下のコードをコピー&ペーストしてください。

{
  "mappings": {
    "wp-content/plugins/copyright-date-block": "./copyright-date-block"
  }
}

ペーストできたら、wp-env(Docker)を再起動します。以下の順番でコマンドを実行してください。

// wp-envを停止
npx wp-env stop

// wp-envを再起動
npx wp-env start

コマンドの実行が完了したら、WordPress管理画面のプラグイン一覧ページを開いてください。

すると、下図のように「Copyright Date Block」というプラグイン名でWordPressにインストールされていることが確認できるかと思います。こちらを有効化してください。

有効化していただいた後、WordPress管理画面左メニュー「投稿」→「新規作成」などでブロックエディタを開いていただき、画面左のインサーターの「ブロック」を開いていただくと、「ウィジェット」カテゴリーの箇所にニッコリマークの「Copyright Date Block」というブロックが選択可能となっているかと思います。

はい、これでブロックのひな形は完成です。現時点ではただの青色の背景色のある文字を表示するだけのブロックとなっておりますが、しっかりとしてブロックが作れたかと思います。

このサンプルのブロックをこれからカスタマイズしていきたいと思います。

ブロックのファイル構成を確認

それでは次に、作成したブロックのファイル構成を確認していきましょう。
ひな形のブロックをカスタマイズする前に、プラグインのファイルの構成を確認することは重要です。

下図の様にVScodeなどのコードエディタで開いてファイルを確認してみましょう。

ちなみに今回作成したのは動的ブロック(ダイナミックブロック)なので、初期状態ではsave.jsファイルは存在しません。ただ、当記事の後半ではsave.jsを新たに追加し、静的レンダリングも有効にできるようにしていきますので、お楽しみにしておいてください。

ある程度ざっと確認できたら、以下の公式ドキュメントの「ブロックのファイル構成」をご確認いただき、各ファイルが何の役割があるのかなどの概要をざっと眺めてください。

今すぐには理解できなくても構いません。当記事で実装を進めていく中で理解を深めていただければ大丈夫です。

block.jsonを編集してブロック情報をカスタマイズ

block.jsonを編集して、ブロックの情報をカスタマイズしていきましょう。

ここでそもそもblock.jsonについてピンとこない方は、以下の公式マニュアルから事前にご確認ください。

block.jsonは立派なブロックプラグインのファイルのひとつになりますので、コードを編集する場合はwp-scriptsのコマンドである「npm start」で編集モードを実行していきましょう。

これにより、JSファイルで編集した内容をいちいちビルド「npm run build」する必要がなく、ファイルを保存時に自動でビルドされて内容が更新されます。

まずwp-envトップディレクトリに作成したブロックのプラグインのディレクトリである「copyright-date-block」へ移動してください。

// wp-envトップディレクトリに作成したブロックのプラグインのディレクトリ「copyright-date-block」へ移動
cd copyright-date-block

copyright-date-blockへ移動できたら、次は以下のコマンドを実行します。

// Node.jsのプロジェクトで定義された「開始コマンド」を実行する命令
npm start

実行できたら、下図のように処理が実行されるかと思います。これでJSファイルを編集したら自動でビルドされるようになりました。

ここまで完了したら、早速block.jsonファイルにて以下の作業を進めていきます。

  • “icon”: の行を削除
  • “description”: の説明文を「Display your site’s copyright date.」に修正

修正後のblock.jsonの内容は以下になります。もし作業が面倒な方は以下のコードをそのままblock.jsonにコピー&ペーストしてください。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/copyright-date-block",
	"version": "0.1.0",
	"title": "Copyright Date Block",
	"category": "widgets",
	"description": "Display your site’s copyright date.",
	"example": {},
	"supports": {
		"html": false
	},
	"textdomain": "copyright-date-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"viewScript": "file:./view.js"
}

上記のように修正できましたら、ブロックエディタで表示を確認してみてください。

まず下図が修正前になるかと思います。

更新していただくと、下図のようにブロックの一部の情報が変更されていることがわかるかと思います。

block.jsonでブロックサポートの追加

次はblock.jsonにてブロックサポートを修正します。

ブロックサポートについてピンとこない方は、以下の公式ドキュメントにて詳細が載っているのでご確認ください。

先ほど修正したblock.jsonの以下の「supports」の箇所を…

"supports": {
	"html": false
},

以下のように修正してください。

"supports": {
    "color": {
        "background": false,
        "text": true
    },
    "html": false,
    "typography": {
        "fontSize": true
    }
},

以下が修正後のblock.jsonの全体のコードになります。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/copyright-date-block",
	"version": "0.1.0",
	"title": "Copyright Date Block",
	"category": "widgets",
	"description": "Display your site’s copyright date.",
	"example": {},
	"supports": {
		"color": {
			"background": false,
			"text": true
		},
		"html": false,
		"typography": {
			"fontSize": true
		}
	},
	"textdomain": "copyright-date-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"viewScript": "file:./view.js"
}

修正して保存したら、ブロックエディタをご確認ください。すると、下図のように画面右側の設置パネルに「色」と「タイポグラフィ」が追加され、テキスト色と文字のサイズを編集できるようになります。

不要なコードを削除してリファクタリング

不要なコードを削除してリファクタリングしましょう。
やることとしては、以下になります。

  • editorStyle行を削除
  • style行を削除
  • viewScript行を削除

修正後のblock.jsonの全体コードは以下になります。block.jsonファイルを開いていただき、以下の様に修正してください。

{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "create-block/copyright-date-block",
    "version": "0.1.0",
    "title": "Copyright Date Block",
    "category": "widgets",
    "description": "Display your site's copyright date.",
    "example": {},
    "supports": {
        "color": {
            "background": false,
            "text": true
        },
        "html": false,
        "typography": {
            "fontSize": true
        }
    },
    "textdomain": "copyright-date-block",
    "editorScript": "file:./index.js",
    "render": "file:./render.php"
}

index.jsを編集する

次は、index.jsを編集します。

index.jsとは、WordPressのブロックエディタ(Gutenberg)で使用するブロックを登録するための、JavaScriptのエントリーポイントファイルです。

このファイルは通常、block.jsonのeditorScript プロパティで指定されており、ブロックエディタ上でのみ読み込まれます。

index.jsの主な役割は、registerBlockType()関数を使ってブロックをエディタに登録することです。
その際、編集画面の表示や挙動を定義するedit.jsや、保存時のHTML構造を定義するsave.jsなどのファイルをインポートして使用します。

つまり、index.jsはブロックを登録する中心的なファイルであり、ブロックの構造や動作を管理する重要な役割を担っています。

ブロック開発において最初に読み込まれるファイルとして、必要な情報や機能を集約し、ブロックの全体像を定義する基礎となります。

こちらに関してもっと詳しく知りたい方は、以下の公式ドキュメントをご確認ください。

それでは編集するのでindex.jsファイルを開いてください。

そしてコード中のregisterBlockType関数を見てください。registerBlockType関数は、インポートしたblock.jsonファイルから取得したブロックの名前と、ブロックの設定オブジェクトを受け取っています。

import Edit from './edit';
import metadata from './block.json';
 
registerBlockType( metadata.name, {
    edit: Edit,
} );

通常ブロックの登録時にはeditプロパティだけを指定すれば動作しますが、必要に応じて「icon」などの他のプロパティも追加することができます。

多くのプロパティはすでにblock.jsonに定義されていますが、カスタムSVGアイコンを使いたい場合は、index.jsでiconプロパティを明示的に指定する必要があります。

registerBlockType関数の箇所を以下のコードに差し替えてください。

const calendarIcon = (
    <svg
        viewBox="0 0 24 24"
        xmlns="http://www.w3.org/2000/svg"
        aria-hidden="true"
        focusable="false"
    >
        <path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm.5 16c0 .3-.2.5-.5.5H5c-.3 0-.5-.2-.5-.5V7h15v12zM9 10H7v2h2v-2zm0 4H7v2h2v-2zm4-4h-2v2h2v-2zm4 0h-2v2h2v-2zm-4 4h-2v2h2v-2zm4 0h-2v2h2v-2z"></path>
    </svg>
);
 
registerBlockType( metadata.name, {
    icon: calendarIcon,
    edit: Edit
} );

ちなみにすべてのブロックのアイコンは24px(ピクセル)の正方形でなければなりません。そのため、viewBoxパラメータにはご注意ください。

index.jsファイルを保存したら、ブロックエディタを確認してください。すると、下図のようにアイコンが変更されていることが確認できたかと思います。

(※この時点でブロックの背景に青い背景色が反映されているのはキャッシュを切り忘れたためになります。みなさまお気をつけください。)

edit.jsを編集する

edit.jsファイルとは、ブロックの動作やエディタ上での見え方を定義するファイルのことを言います。

現在の状態では、ユーザーに「Copyright Date Block – hello from the editor!」という文字がただ表示されるだけになっています。

このメッセージをユーザーが変更できる様にするために、edit.jsファイルを開き、Edit()関数がHTMLのpタグを使ってこのデフォルトの文字を返していることを確認してください。

export default function Edit() {
    return (
        <p { ...useBlockProps() }>
            { __(
                'Copyright Date Block – hello from the editor!',
                'copyright-date-block-demo'
            ) }
        </p>
    );
}

上記コードのuseBlockProps()関数は、ブロックのラッパー要素に必要なCSSクラスや属性を自動で付与します。そして、__()(ダブルアンダースコア)は、表示するテキストを国際化(翻訳可能)するための関数です。第1引数が表示テキスト、第2引数がテキストドメインです。

ブロックのラッパーについて詳しく知りたい方は以下をご確認ください。

また、国際化対応について知りたい方は以下をご確認ください。

ちなみに現在実装しているコピーライトブロックの主な目的は、著作権記号(©)と現在の年を表示することです。そのため、まずは現在の年を取得して文字列として表示できるようにする必要があります。

以下のコードは、JavaScriptを使って現在の年を文字列形式で取得するコードになります。

const currentYear = new Date().getFullYear().toString();

上記コードを使用して、以下のように現在の年を表示するように修正します。

export default function Edit() {
    const currentYear = new Date().getFullYear().toString();
 
    return (
        <p { ...useBlockProps() }>© { currentYear }</p>
    );
}

上記コードを記述してedit.jsを保存したら、ブロックエディタを更新してください。著作権記号 (©) と現在の年が表示されているかと思います。

render.phpを編集する

render.phpとは、WordPressのブロック開発において動的ブロック(dynamic block:ダイナミックブロック)を扱うときに使われるPHPファイルのことを言います。

render.phpはブロックのHTML出力をPHPで生成するファイルです。

通常固定的な内容を出力する静的ブロックはJavaScript側のedit.jsやsave.jsで完結しますが、「投稿日時」や「現在の年」などの動的な内容を含む場合は、PHPでレンダリングする必要があります。

ここまでの実装だと、エディタ上ではブロックは正しく動作していますが、フロントエンドではデフォルトのただの「」という文字が表示されたままです。これを動的に正しく表示できるように修正するにはrender.phpファイルを修正します。

修正前だと以下の様なコードになっているかと思います。

<p <?php echo get_block_wrapper_attributes(); ?>>
    <?php esc_html_e( 'Copyright Date Block – hello from a dynamic block!', 'copyright-date-block' ); ?>
</p>

エディタ内でのedit.jsでのuseBlockProps()関数と同様に、get_block_wrapper_attributes()関数は、ブロックのラッパー要素に必要なすべての CSS クラスやスタイルを自動的に出力してくれます。

あとは、中身となるコンテンツ部分を出力するだけです。

現在の年をPHPで取得するには、以下のようにdate(“Y”)関数を使います。その結果、render.phpのコードは以下のようになります。以下のコードをコピーしてrender.phpの全体にペーストしてください。

<p <?php echo get_block_wrapper_attributes(); ?>>© <?php echo date( "Y" ); ?></p>

ペーストが完了したら、ブロックを追加しているページをフロントから確認してみてください。

修正前では下図の様になっていたかと思いますが…

修正後は、下図の様にちゃんとコピーライトアイコンと動的に現在の年が表示されているかと思います。

クリーンアップ作業

@wordpress/create-blockパッケージを使ってブロックのひな形を作成すると、実際には使わないファイルやコードが含まれていることがあります。

ここでは、スタイルシートやフロントエンド用のJavaScriptを使っていないため、以下の手順で「src/」フォルダー内をクリーンアップ(整理)しましょう

  1. edit.jsファイルで、editor.scssのimport 行を削除する。
  2. index.jsファイルで、style.scssのimport 行を削除する。
  3. editor.scss、style.scss、view.jsファイルを削除する。

上記が作業が完了したら変更がすべて保存されていることを確認し、「npm run start」コマンドを終了して「npm run build」コマンドを実行し、コードを最適化しつつ本番環境用にビルドします。

これで、余計なコードを省いたWordPressブロックの構成になったかと思います。

ただし、ここで終わりではありません。
次のセクションでは、さらに機能を追加し、静的レンダリング(save.js)にも対応させていきます。

ここまでで、ファイルの構成は下図の様になっているかと思います。

ここまでで、ブロック開発の基本中の基本の実装が一通り完了しました。

一旦ここまで作成してきた状態のブロックファイルをダウンロードできるように用意いたしましたので、ご自身でちゃんとできているか確認などする際にご利用ください。

ブロック属性を追加する

ここまで作成したコピーライトブロックは現在の年を表示していますが、例えば「@ 2017-2025」の様に、開始の年も合わせて表示したい場合があります。

この機能を実装するには、ユーザーがブロック内で「開始の年」を入力できるようにする必要があります。また、「開始年を表示するかどうか」を切り替えるオン/オフ機能も必要です。

こうした機能を実現するには、WordPressブロックの「属性(attributes)」という仕組みを使います。

属性(attributes)についてピンとこない方は、以下の公式ドキュメントにて詳しく解説しておりますので、よろしければご確認ください。

block.jsonを編集する

ブロックの属性(attributes)は、通常block.jsonファイルで定義します。

block.jsonファイルを開いて、example プロパティのすぐ下に以下のようなattributesセクションを追加してください。

"example": {},
"attributes": {
    "showStartingYear": {
        "type": "boolean"
    },
    "startingYear": {
        "type": "string"
    }
},

属性を定義するときは、必ずtypeを指定する必要があります。

showStartingYearは、開始年を表示するかどうかを制御する属性です。オン/オフの切り替えなので、boolean(真偽値)型を指定します。

startingYearは、ユーザーが入力する「開始年」の値を保存する属性です。数字を扱いますが、ここではシンプルに文字列(string)として扱います。

ここまでで、block.jsonの全体のコードは以下の様になっているかと思います。

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/copyright-date-block",
	"version": "0.1.0",
	"title": "Copyright Date Block",
	"category": "widgets",
	"description": "Display your site’s copyright date.",
	"example": {},
	"attributes": {
		"showStartingYear": {
			"type": "boolean"
		},
		"startingYear": {
			"type": "string"
		}
	},
	"supports": {
		"color": {
			"background": false,
			"text": true
		},
		"html": false,
		"typography": {
			"fontSize": true
		}
	},
	"textdomain": "copyright-date-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"render": "file:./render.php",
	"viewScript": "file:./view.js"
}

ユーザーインターフェース(InspectorControls)の追加

当記事の前半では、ブロックサポートを追加することで、ブロックエディタの設定パネルに「色」や「タイポグラフィ」などのパネルが自動的に表示されました。

今回はそれに加えて、独自のカスタムパネルをサイドバー(設定パネル)に表示する方法を紹介します。これには、InspectorControlsコンポーネントを使います。

IInspectorControls

InspectorControlsは、@wordpress/block-editorパッケージに含まれており、ブロックエディタのサイドバー(設定パネル)に設定UIを追加するためのコンポーネントです。

まず、edit.jsファイルのimport文にInspectorControlsを追加しましょう

import { InspectorControls, useBlockProps } from '@wordpress/block-editor';

次に、Edit関数のJSXを以下のようにコードを修正してください。

export default function Edit() {
    const currentYear = new Date().getFullYear().toString();
 
    return (
        <>
            <InspectorControls>
                Testing
            </InspectorControls>
            <p { ...useBlockProps() }>© { currentYear }</p>
        </>
    );
}

上記コードの「<></>」はReactのフラグメント構文で、複数の要素をまとめて返すために使います。また、InspectorControlsの中に書いた「Testing」は仮の表示テキストです。

修正後に保存が完了したら、ブロックエディタをご確認ください。すると、下図の様に設定パネルに「Testing」という文字が表示されているのが確認できるかと思います。

コンポーネントとパネル

次はカスタムパネルと開始の年の表示機能のインターフェイスを追加するために、いくつかのWordPressコアのコンポーネントを追加で使用します。

WordPressコアのコンポーネントとして、PanelBodyTextControlToggleControl を @wordpress/components パッケージからインポートして使用します。

edit.jsファイルの他のインポートの下に以下の行を追加してください。

import { PanelBody, TextControl, ToggleControl } from '@wordpress/components';

次に先ほどの「Testing」の表示を、PanelBodyコンポーネントで囲んでパネル化します。
パネルのタイトルは「Settings」とし、WordPressの翻訳関数 __()関数を使って国際化します。

インポートの追加に加えてedit.jsファイルに以下のコードを反映し修正してください。

export default function Edit() {
    const currentYear = new Date().getFullYear().toString();
 
    return (
        <>
            <InspectorControls>
                <PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
                    Testing
                </PanelBody>
            </InspectorControls>
            <p { ...useBlockProps() }>© { currentYear }</p>
        </>
    );
}

修正が完了したら、ブロックエディタをご確認ください。下図の様に設定パネルに「Settings」というタイトルのパネルが表示され、その中に「Testing」という文字が表示されるはずです。

Textコントロール

次のステップでは、「Testing」という仮のテキスト表示をTextControlコンポーネントに置き換えて、ユーザーが「開始の年」を直接入力できるようにします。

そのためには、まずedit.jsファイルのEdit()関数を以下のように書き換え、ブロックの属性(attributes)とその更新関数(setAttributes)を受け取れるようにします。

export default function Edit( { attributes, setAttributes } ) {
    const { showStartingYear, startingYear } = attributes;
    ...

上記コードの様に、Edit()関数に以下の2つのパラメータを含める必要があります。

  • attributesは、ブロックのすべての属性(attributes)を含むオブジェクトです。
  • setAttributesは、属性(attributes)の値を更新するための関数です。

コードに上記のパラメータが含まれることで、showStartingYear属性とstartingYear属性を取得できます。

次に、メッセージ「Testing」を削除して、TextControlコンポーネントを追加します。

export default function Edit( { attributes, setAttributes } ) {
    const { showStartingYear, startingYear } = attributes;
    const currentYear = new Date().getFullYear().toString();
 
    return (
        <>
            <InspectorControls>
                <PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
                    <TextControl
                        __nextHasNoMarginBottom
                        __next40pxDefaultSize
                        label={ __(
                            'Starting year',
                            'copyright-date-block'
                        ) }
                        value={ startingYear || '' }
                        onChange={ ( value ) =>
                            setAttributes( { startingYear: value } )
                        }
                    />
                </PanelBody>
            </InspectorControls>
            <p { ...useBlockProps() }>© { currentYear }</p>
        </>
    );
}

TextControlコンポーネントには以下のパラメーターが含まれます。

  • label:テキスト入力フィールドのラベルを設定。
  • value:現在の属性の値(空文字との論理和で未入力状態を防止)。
  • onChange:値が変更されたときに属性を更新。

ちなみに上記コードのように「startingYear || ” 」と書くことで、startingYearが未定義のときでもReactの警告を回避できます(「制御されたコンポーネント vs 非制御コンポーネント」問題)。

ブロックエディタをご確認いただくと、下図の様に設定パネルのUIがテキストを入力して保存できる状態になっているかと思います。

Toggleコントロール

次は、ユーザーが「開始の年を表示するかどうか」を切り替えられるように、トグルスイッチ(ToggleControl)を追加します。

このトグルは、showStartingYear 属性を制御するために使用します。

ToggleControlが使用できるプロパティは以下になります。

  • label:表示名。「Show starting year」とします。
  • checked:現在の状態(オン/オフ)を表します。showStartingYearを設定。
  • onChange:トグルが切り替えられたときにshowStartingYearを更新します。

また、前回追加したTextControl(開始の年入力欄)は、showStartingYearがtrueのときだけ表示されるように変更します。これは「&&論理演算子」を使って条件付きで描画します。

edit.jsファイルの内容を以下のコードに修正してください。

export default function Edit( { attributes, setAttributes } ) {
    const { showStartingYear, startingYear } = attributes;
    const currentYear = new Date().getFullYear().toString();
 
    return (
        <>
            <InspectorControls>
                <PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
                    <ToggleControl
                        checked={ !! showStartingYear }
                        label={ __(
                            'Show starting year',
                            'copyright-date-block'
                        ) }
                        onChange={ () =>
                            setAttributes( {
                                showStartingYear: ! showStartingYear,
                            } )
                        }
                    />
                    { showStartingYear && (
                        <TextControl
                            __nextHasNoMarginBottom
                            __next40pxDefaultSize
                            label={ __(
                                'Starting year',
                                'copyright-date-block'
                            ) }
                            value={ startingYear || '' }
                            onChange={ ( value ) =>
                                setAttributes( { startingYear: value } )
                            }
                        />
                    ) }
                </PanelBody>
            </InspectorControls>
            <p { ...useBlockProps() }>© { currentYear }</p>
        </>
    );
}

修正が完了したら、ブロックエディタを更新して確認してみてください。すると、下図の様にラジオボタンが表示されているかと思います。

ラジオボタンをクリックすれば、下図の様にテキスト入力欄が表示され、入力できるようになっているかと思います。

ブロックのコンテンツの表示の更新

ここまでで、ユーザーが「開始の年」を入力し、表示のオン/オフを切り替えられるUIが完成しました。次は、実際にブロックエディタ上でブロックの表示内容を更新します。

実装イメージとして、以下のコードのように新しいdisplayDate変数を作って、showStartingYearがtrueで、startingYearに値があるとき、例えば「2020–2025」のように、開始年と現在の年をダッシュ「–」でつなぎます。

それ以外のときはcurrentYearを表示して現在の年(例えば「2025」)だけを表示します。

let displayDate;
 
if ( showStartingYear && startingYear ) {
    displayDate = startingYear + '–' + currentYear;
} else {
    displayDate = currentYear;
}

ちなみに上記コードのようにletを使うのは、値を条件によって変えるためです。constでも書き換え可能ですが、柔軟性を持たせるためletを使っています。

そして以下が TextControl、ToggleControl、そしてdisplayDate変数を活用した完成形のコードです。edit.jsのコードを以下のコードに修正してください。

export default function Edit( { attributes, setAttributes } ) {
    const { showStartingYear, startingYear } = attributes;
    const currentYear = new Date().getFullYear().toString();
 
    let displayDate;
 
    if ( showStartingYear && startingYear ) {
            displayDate = startingYear + '–' + currentYear;
    } else {
        displayDate = currentYear;
    }
 
    return (
        <>
            <InspectorControls>
                <PanelBody title={ __( 'Settings', 'copyright-date-block' ) }>
                    <ToggleControl
                        checked={ !! showStartingYear }
                        label={ __(
                            'Show starting year',
                            'copyright-date-block'
                        ) }
                        onChange={ () =>
                            setAttributes( {
                                showStartingYear: ! showStartingYear,
                            } )
                        }
                    />
                    { showStartingYear && (
                        <TextControl
                            label={ __(
                                'Starting year',
                                'copyright-date-block'
                            ) }
                            value={ startingYear || '' }
                            onChange={ ( value ) =>
                                setAttributes( { startingYear: value } )
                            }
                        />
                    ) }
                </PanelBody>
            </InspectorControls>
            <p { ...useBlockProps() }>© { displayDate }</p>
        </>
    );
}

修正が完了したら、ブロックエディタを更新して確認し、開始の年を入力してみてください。すると下図の様に表示が更新されるかと思います。

ただしこのままだとブロックエディタ上のみしか表示を更新できないので、次にrender.phpを編集することで、フロント表示時にも内容が正しく反映される様にします。

render.phpを編集

ここまでで、ブロックエディタ側では「開始の年の入力」と「表示切り替え」のUIが完成しました。
次は、フロントの表示(実際のページの表示)にも同じブロックの表示を反映するために、render.phpを修正します。

以下のコードの様に、まず$display_date変数を追加して、Edit()関数での実装を繰り返します。

$display_date変数には、startingYear属性の値と$current_year変数を「-」ダッシュで区切って表示するか、もしくは、showStartingYear属性がfalseのとき$current_yearの値だけを表示します。

if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
    $display_date = $attributes['startingYear'] . '–' . $current_year;
} else {
    $display_date = $current_year;
}

ちなみにrender.phpでは、以下の3つの変数が備わっております。これらを使用してブロックの出力をカスタマイズすることができます。

  • $attributes (array):ブロックの属性
  • $content (string):ブロックのデフォルトコンテンツ
  • $block (WP_Block):ブロックのインスタンス

最終的にはrender.phpファイルの全体のコードは以下のようになります。以下のコードをrender.phpへコピー&ペーストしてください。

<?php
$current_year = date( "Y" );
 
if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
    $display_date = $attributes['startingYear'] . '–' . $current_year;
} else {
    $display_date = $current_year;
}
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
    © <?php echo esc_html( $display_date ); ?>
</p>

完了したら保存して、フロントの表示を確認してください。

すると、下図のようにフロント表示でも開始の年が反映されてちゃんと表示されているのが確認できるかと思います。

これで、動的レンダリングを用いたカスタムブロックの作成が完了しました。

このブロックでは、WordPress のブロックサポート機能やコアコンポーネント(TextControl や ToggleControl)、そしてカスタム属性を活用することで、柔軟で実用的な機能を実現しています。著作権記号(©)と日付を表示するというシンプルな目的ながら、多くの場面で十分に活用できるブロックが完成しました。

しかし、当記事の実装の解説はこれで終わりではありません。

次のステップでは、「静的レンダリング」の仕組みをブロックに追加していきます。WordPress がブロックのデータをどのように保存しているのかを理解し、万が一プラグインが無効化されてしまった場合にも、ブロックの内容が正しく表示されるように、フォールバック(代替処理)の実装にも取り組みます。

このセクションでは、より堅牢で持続性のあるブロック設計の考え方を学ぶことができます。

ここでも一旦ここまで作成してきた状態のブロックファイルをダウンロードできるように用意いたしましたので、ご自身でちゃんとできているか確認などする際にご利用ください。

静的レンダリングの追加

WordPressブロックは、以下のいずれかの方法でレンダリング(表示)されます。

  • 動的レンダリング(Dynamic Rendering・ダイナミックブロック)
  • 静的レンダリング(Static Rendering・静的ブロック)
  • 動的レンダリングと静的レンダリングの組み合わせ

そして、ここまでで作成したブロックは、動的レンダリングによって表示されるものでした。

「動的レンダリング」とは、ブロックのマークアップ(HTML)がデータベースには保存されず、代わりに属性(attributes)だけが保存される仕組みです。ページを表示するたびにPHPファイル(render.php)が実行されHTMLを生成します。

まとめると以下になります。

  • HTMLの出力は保存されない
  • 属性(attributes)だけがデータベースに保存される
  • 表示時にPHP(render.php)が実行され、HTMLが生成される

「静的レンダリング」では、ブロックのマークアップ(HTML)と属性(attributes)の両方が、投稿コンテンツとしてそのままデータベースに保存されます。つまり、プラグインが無効化された場合でも、ブロックの内容が失われることなくそのまま表示されるというメリットがあります。

まとめると以下になります。

  • ブロックのHTMLマークアップと属性がそのまま保存される
  • 投稿コンテンツ内にHTMLが含まれるため、PHPコードなしでも表示可能

そして3つ目の「動的レンダリングと静的レンダリングの組み合わせ」では、その名の通りブロックを動的と静的の両方の特性を組み合わせて作成することができます。

たとえば、基本的な表示部分は静的に保存し、特定の条件に応じてフロントエンドで動的に処理を追加するという作り方が可能です。

実際にエディタを「コードエディター」モードに切り替えると、ここまで作成してきた現時点の動的ブロックは次のように表示されます。

ご確認いただくとお分かりの通り、以下のように動的ブロックはHTMLを含まない短いコメント形式で記録されます。

<!-- wp:create-block/copyright-date-block {"showStartingYear":true,"startingYear":"2017"} /-->

これに対して、段落ブロックなどの静的ブロックは次のように、HTMLを含む形式で保存されます。

<!-- wp:paragraph -->
<p>This is a test.</p>
<!-- /wp:paragraph -->

この違いからも分かるように、静的ブロックはHTMLが保存されるため、WordPressがブロックを認識できない場合でも、表示そのものが失われることはありません。

ここからは、現時点まで作成した動的ブロックであるコピーライトブロックに静的レンダリングの仕組みを追加することで、より安全で壊れにくいブロックにしていきます。

これにより、プラグインが無効化されてしまったときのフォールバック(代替)機能としても機能するようになります。

動的レンダリングと静的レンダリングについて詳しく知りたい方は、以下の公式ドキュメントページをご活用ください。

ほとんどのブロックは動的または静的のどちらかでレンダリングされる形で作られてますが、ここで解説するように、両方の方法を利用するブロックも作成できます。

静的レンダリングを追加する理由

動的レンダリングされるブロックに静的レンダリングを追加しても、引き続きrender.phpファイルがフロントエンドの出力を制御します。ただし、ブロックのHTMLコンテンツが投稿内に保存されるようになります。

これにより、万が一プラグインが削除されたり無効化された場合でも、コンテンツ自体は消えずに残ります。たとえばこの現在作成しているコピーライトブロックでは、プラグインが削除されてもブロックの内容はカスタムHTML ブロックとして自動的に変換され、必要に応じて段落ブロックなどに再変換することも可能です。

プラグインが無効化され、ブロックが利用できなくなった場合、ブロックが見つからないという通知(エラーメッセージ)がブロックエディタに表示されます。

しかし、静的レンダリングを追加しておけば、その通知が出ても、コンテンツ自体はHTMLとして残り、サイト上に問題なく表示されます。

このように、すべてのブロックで静的レンダリングが必要というわけではありませんが、フォールバック(予期せぬ事態への備え)として有効です。

さらに、ブロックのマークアップがブロックパターンやテーマテンプレートに含まれている場合も考慮しましょう。

例えば、現在作成中のコピーライトブロックが含まれるテーマやブロックパターンを使った際に、ユーザーがまだそのブロックを提供するプラグインをインストールしていなかったとします。

その場合、WordPressは「このブロックは利用できません」という通知を表示しますが、HTMLコンテンツ自体は表示されるため、ユーザー体験が大きく損なわれることはありません。

save関数の追加

それでは早速コードを修正していきましょう。

「src/」フォルダ内に新しくsave.jsファイルを作成し、以下のコードを追加します。

import { useBlockProps } from '@wordpress/block-editor';
 
export default function save() {
    return (
        <p { ...useBlockProps.save() }>
            { 'Copyright Date Block – hello from the saved content!' }
        </p>
    );
}

イメージとしては下図の様になります。

上記コードはedit.jsの記述とよく似ています。useBlockProps.save()は、保存時に必要なクラスや属性を自動的に追加してくれます。詳細はブロックラッパーのドキュメントを参照してください。

次に、index.jsファイルでsave()関数をインポートし、registerBlockType()にsaveプロパティを追加します。index.jsにて以下の様にコードを修正してください。

import save from './save';
 
...
 
registerBlockType( metadata.name, {
    icon: calendarIcon,
    edit: Edit,
    save
} );

上記コードの様に、プロパティ名と変数名が同じ場合、省略形で書くことができます。つまり上のコードのsaveは「save: save」と同等の意味になります。

save.jsとindex.jsを保存してブロックエディタを更新すると、下図の様にブロックバリデーションエラーが表示されるかと思います。

これは想定された動作なので心配ありません。ブラウザでデベロッパーツールを開くと、以下のようなメッセージが表示されるはずです。

このブロックのバリデーションエラーは、save.jsファイルのsave()関数はブロックの内容を返すものの、以前に保存されたブロックがrender.phpによって動的にレンダリングされていたため、ブロックのマークアップにHTMLが保存されていないために発生します。

そして、以下の保存内容が現時点のマークアップであることを思い出してください。

<!-- wp:create-block/copyright-date-block {"showStartingYear":true,"startingYear":"2017"} /-->

保存されているブロックのマークアップが上記のままであれば、ブロックバリデーションエラーが繰り返し表示されることになります。

そのため、下図の様に「ブロックのリカバリーを試行」をクリックしてください。

リカバリーを実行した後にコードエディターを開くと、マークアップは以下のように修正されているのが確認できるかと思います。

コードとしては以下の様な感じです。

この時点では、まだ「Copyright Date Block – hello from the saved content!」というただの文字が表示されるだけです。

<!-- wp:create-block/copyright-date-block {"showStartingYear":true,"startingYear":"2017"} -->
<p class="wp-block-create-block-copyright-date-block">Copyright Date Block – hello from the saved content!</p>
<!-- /wp:create-block/copyright-date-block -->

このように、ブロックエディタでは一時的に「ブロックのバリデーションエラー」が表示されることがあります。

エディター上に表示される「ブロックのリカバリーを試行」ボタンをクリックし、ページを再読み込みすれば問題は解消されます。

save.jsを修正

次にsave()関数を修正して、エディタに保存されるブロックの内容が正しく表示されるようにしましょう。

まずは、以下の様にedit.jsと同様のロジックをsave.jsに追加します。

  • save()関数にattributesパラメータを追加します。
  • showStartingYearとstartingYearをattributesから取得します。
  • currentYearという変数に現在の年(文字列)を代入します。
  • displayDateという変数に、showStartingYearの状態とstartingYearの有無に応じて表示内容を決定します。

save.jsファイルを開いたら、以下のコードの様に修正してください。

export default function save( { attributes } ) {
    const { showStartingYear, startingYear } = attributes;
    const currentYear = new Date().getFullYear().toString();
 
    let displayDate;
 
    if ( showStartingYear && startingYear ) {
        displayDate = startingYear + '–' + currentYear;
    } else {
        displayDate = currentYear;
    }
 
    return (
        <p { ...useBlockProps.save() }>© { displayDate }</p>
    );
}

ファイルを保存したら、ブロックエディタに戻ってページを更新し、「ブロックのリカバリーを試行」をクリックしてください。

コードエディターで確認すると、以下のようなマークアップが投稿に保存されているはずです。

コードとしては以下の様な感じです。

ご確認いただくと、さっきまでは「Copyright Date Block – hello from the saved content!」というただの文字が表示されるだけでしたが、今度は正しく「© 2017–2025」と表示されていることがわかります。

(※2025年時点で動作を確認しているためここでは「2025」となっておりますが、この部分は現在の年となっているかと思います)

<!-- wp:create-block/copyright-date-block {"showStartingYear":true,"startingYear":"2017"} -->
<p class="wp-block-create-block-copyright-date-block">© 2017–2025</p>
<!-- /wp:create-block/copyright-date-block -->

この時点で、エディタとフロントエンドの両方でブロックが正しく動作しているように見えます。ブロックの HTML は投稿データに保存され、render.phpによる動的レンダリングも併用されている状態です。

しかし、ここでひとつ課題があります。

たとえば、2023年にこのブロックを使用してページを作成し、そのページを2024年になって再編集しようとした場合を考えてみましょう。

フロントエンドでは、render.php によって動的に処理されるため、常に最新の年(この場合は 2024 年)が表示されるため問題はありません。

ところが、エディタ側では事情が異なります。エディタに表示される内容はsave.jsによって保存された HTMLがもとになっており、このHTMLには作成時(2023年)の年がそのまま残っているため、「© 2017–2023」のように表示されます。

この状態でエディタを開くと、保存されたHTMLとsave.jsの出力が一致しないため、WordPressは「ブロックのバリデーションエラー」として警告を表示します。

この問題の根本的な原因は、save.jsがブロックを保存する際に「new Date().getFullYear()」を使用しており、その時点の年を静的に書き込んでしまうことにあります。つまり、年が変わっても保存済みのコンテンツは自動的には更新されないのです。

この問題を解消する方法については、次のセクションで解説します。

静的レンダリングされるブロック内の動的コンテンツの処理

通常、静的にレンダーされるブロックでは、動的なコンテンツは使わないことが望まれます。これは「動的レンダリング」という言葉が使われる理由のひとつでもあり、動的な処理が必要な場合はrender.phpなどに任せるべきという原則があります。

そして、静的レンダリングと動的レンダリングを組み合わせて使う場合には注意が必要です。

特に今回の実装のように、年が変わった時にエディタでブロックのバリデーションエラーが発生してしまう問題を防ぐにはもう少し工夫が必要です。

年が変わった時にエラーになる問題の原因は、save()関数の中でcurrentYear(現在の年)が「毎回自動で計算される=動的に変化する」ことにあります。

静的レンダリングでは、本来このような値は静的に設定された変数として扱うべきです。
そのため、currentYearをJavaScriptのDate()関数で毎回計算するのではなく、新しいブロック属性(attributes)として保存することで、この問題を解決できます。

解決するには、block.jsonファイルを開き、以下のコードの様に新しい属性としてfallbackCurrentYearを追加します。

"attributes": {
    "fallbackCurrentYear": {
        "type": "string"
    },
    "showStartingYear": {
        "type": "boolean"
    },
    "startingYear": {
        "type": "string"
    }
},

次にsave.jsファイルを開き、currentYearの代わりにblock.jsonで新規追加したfallbackCurrentYear属性を使用します。save()関数を以下のコードの様に修正してください。

export default function save( { attributes } ) {
    const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
 
    let displayDate;
 
    if ( showStartingYear && startingYear ) {
        displayDate = startingYear + '–' + fallbackCurrentYear;
    } else {
        displayDate = fallbackCurrentYear;
    }
 
    return (
        <p { ...useBlockProps.save() }>© { displayDate }</p>
    );
}

ここで、fallbackCurrentYearがundefined(未定義)の場合に何が起きるかを考えてみましょう。

先ほどまでは、currentYearをsave()関数内でJavaScriptのDate()関数によって直接定義していたため、たとえshowStartingYearやstartingYearが未定義であっても、関数は必ず何らかのコンテンツ(たとえば現在の年)を返していました。

しかし、今回のようにcurrentYearをfallbackCurrentYear属性として外部から受け取る方式に変更すると、この値が存在しない場合(つまり undefined の場合)、返すべき内容がなくなる可能性があります。

このような状況に備えて、fallbackCurrentYearが未定義であればnullを返すようにしておきましょう。つまり、不完全な HTML を無理に保存するよりも、何も保存しない方が望ましいという考え方です。

結果として、最終的なsave.jsファイルのsave()関数は次のようになります。

export default function save( { attributes } ) {
    const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
 
    if ( ! fallbackCurrentYear ) {
        return null;
    }
 
    let displayDate;
 
    if ( showStartingYear && startingYear ) {
        displayDate = startingYear + '–' + fallbackCurrentYear;
    } else {
        displayDate = fallbackCurrentYear;
    }
 
    return (
        <p { ...useBlockProps.save() }>© { displayDate }</p>
    );
}

edit.jsでの属性の設定

save()関数では、新しく追加したfallbackCurrentYear属性を使用しています。

しかし、このfallbackCurrentYear属性にはどこかで値を設定しておく必要があります。そこで、その役割をedit.jsファイルのEdit()関数で担いましょう。

まずは、edit.jsファイルを開き、Edit()関数の先頭で他の属性と一緒にfallbackCurrentYearを取得します。

export default function Edit( { attributes, setAttributes } ) {
    const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;

... 省略 ...

次に、関数内で現在の年を示すcurrentYearを取得し、それを使ってブロックの内容を構成します。

export default function Edit( { attributes, setAttributes } ) {
    const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
 
    // 現在の年を取得し、文字列であることを確認する
    const currentYear = new Date().getFullYear().toString();

... 省略 ...

重要なのはここからです。

ブロックがエディタで読み込まれたとき、もしfallbackCurrentYearが未設定(または値が異なる)であれば、現在の年をfallbackCurrentYear属性にセットする必要があります。

この処理を行うには、以下の様にコードを追加する必要があります。

if ( currentYear !== fallbackCurrentYear ) {
    setAttributes( { fallbackCurrentYear: currentYear } );
}

この条件文は、「現在の年 (currentYear) とfallbackCurrentYear が一致していない場合」にのみ、属性を更新します。

この対応により、save.js側では常に信頼できるfallbackCurrentYearの値を使ってマークアップを生成でき、年の変化によるバリデーションエラーも回避できます。

そしてブロックが初期化されたときに一度だけこの処理が実行されるようにするには、ReactのuseEffectフックを使うのが効果的です。

まず、edit.jsファイルにてuseEffectをインポートします。

import { useEffect } from 'react';

次に、Edit()関数の中でcurrentYearを定義した直後に、以下のようなuseEffectを追加します。

export default function Edit( { attributes, setAttributes } ) {
    const { fallbackCurrentYear, showStartingYear, startingYear } = attributes;
 
    // 現在の年を取得し、文字列であることを確認する
    const currentYear = new Date().getFullYear().toString();
 
    // ブロックロードのとき、fallbackCurrentYear がまだ設定されていなければ、
    // 現在の年に設定する
    useEffect( () => {
        if ( currentYear !== fallbackCurrentYear ) {
            setAttributes( { fallbackCurrentYear: currentYear } );
        }
    }, [ currentYear, fallbackCurrentYear, setAttributes ] );
 
    ...

これにより、ブロックがエディタに読み込まれたとき、fallbackCurrentYearが未設定または異なる年であれば、現在の年を属性にセットする処理が一度だけ実行されます。

そして、エディタでブロックが読み込まれると、fallbackCurrentYear属性が自動的に設定されます。この値はsave()関数内で使用され、保存されるブロックのHTMLを生成するために使われます。そのため、ブロックのバリデーションエラーが発生せずに、正しいコンテンツがエディタに表示されます。

ただし、注意点があります。それは「年が変わる場合」です。

たとえば、あるページにコピーライトブロックを2023年に追加したとします。そして、2024年にそのページを再編集した場合、currentYearは2024を返しますが、保存されていたfallbackCurrentYearは2023のままです。

このとき、エディタはfallbackCurrentYearとcurrentYearの不一致を検出し、属性を自動的に2024に更新します。これにより、save()関数が返すHTMLも2024年を含む内容に更新されます。

このようにuseEffectを使うことで、不要な再レンダーや属性更新を避け、より効率的なブロックの初期化処理が可能になります。

render.phpの最適化

最後に行うべきなのは、render.phpの最適化です。

まず、currentYear属性とfallbackCurrentYear属性が同じ場合は、すでにsave.jsによってブロックのHTMLがデータベースに保存されているため、動的にコンテンツを生成する必要はありません。このときは、$content変数の中身をそのまま使えば OK です。

一方、currentYearとfallbackCurrentYearが異なる場合、年が変わったと判断され、現在の年に基づいたHTMLを再生成して表示する必要があります。これにより、年が変わっても常に最新の情報がフロントエンドに表示されるようになります。

render.phpの最終的なコードは以下の通りです。

$current_year = date( "Y" );
 
// どのコンテンツを表示するかを決定する。
if ( isset( $attributes['fallbackCurrentYear'] ) && $attributes['fallbackCurrentYear'] === $current_year ) {
 
    // 現在の年はフォールバックと同じ。save.js 関数で保存された、データベース内のブロックコンテンツを使用する
    $block_content = $content;
} else {
 
    // 現在の年はフォールバックと異なる。更新されたブロックコンテンツをレンダーする
    if ( ! empty( $attributes['startingYear'] ) && ! empty( $attributes['showStartingYear'] ) ) {
        $display_date = $attributes['startingYear'] . '–' . $current_year;
    } else {
        $display_date = $current_year;
    }
 
    $block_content = '<p ' . get_block_wrapper_attributes() . '>© ' . esc_html( $display_date ) . '</p>';
}
 
echo wp_kses_post( $block_content );

これで、静的レンダリングによって保存された内容と、動的レンダリングによって最新の情報に更新される仕組みが両立された、柔軟なカスタムブロックが完成しました。

プラグインが無効化された場合でも、保存された内容はそのまま残り、年が変わったときは自動で更新されるため、長期的に安心して使えるブロックになります。

これで当記事のコピーライトブロックプラグインは完成です。お疲れ様でした!

長かったですね…笑

完成イメージは下図の様になります。(やっとCSSのキャッシュを消しました…笑)

フロントではざっくり下図の様なイメージかと思います。

ここまでの完成系のプラグインファイルをダウンロードできるように用意いたしましたので、ご自身でちゃんとできているか確認などする際にご利用ください。

また、もしダウンロードいただいたサンプルダウンロードファイルでエラーが起こってしまう場合は、以下のWordPress公式が公開しているGithubからダウンロードしてファイルを確認したり動作確認してみてください。

https://github.com/WordPress/block-development-examples/tree/trunk/plugins/copyright-date-block-09aac3

ブロック運用のためのdeprecated対応について

今回WordPressのブロックを自作で作っていきましたが、ブロックを本格的に運用するとなると、ブロック機能を開発した土台がプラグインにしてもテーマにしても、アップデートを行う中でどこかでエラーが起こってしまうことがあります。

そもそもソフトウェア開発では、何もメンテナンスせずに放っておくといつか必ず壊れるという時が来るものです。

そこでWordPressのブロックの運用のために必須と言っても過言ではない仕組みがdeprecated対応です。

deprecated(非推奨)とは、ブロックの古いバージョンをサポートしつつ、ブロックの新しいバージョンを導入するための重要な仕組みのことを言います。

例えば、ブロックの機能を追加拡張することとなった場合、データベースのブロックのHTMLとsave.jsに違いが起こり、下図の様にブロックがエディタ上で壊れてしまう場合があります。

このような事態を解決してくれるのがdeprecated対応です。

deprecated対応は、品質向上にも関わる非常に重要な技術なので当記事の実装方法と合わせて必ずご確認いただくことをおすすめします。

ここで筆者の執筆した記事で恐縮ですが、以下deprecated対応について詳しく解説いたしましたので、もしよろしければお仕事などでご活用いただけましたら幸いです。

まとめ

WordPressのブロックを自作する方法について、初心者の方にもわかりやすく解説してきました。

WordPressには初期状態から多くのブロックが用意されていますが、実際にサイトを運営していると「こんなブロックがあったらいいのに…」と感じることも多いのではないでしょうか。

そんなときこそ、自分でブロックを開発できるスキルが役に立ちます。

当記事では、公式ドキュメントのチュートリアルをベースにしつつ、独自の視点を加えて解説を行いました。カスタムブロックの基本から応用までを実践的に紹介していますので、テーマ開発やプラグイン開発、Web制作のお仕事など、さまざまな場面で活用していただける内容となっています。

ぜひ本記事を参考に、オリジナルのブロック作成にチャレンジしてみてください。

執筆者

UMENOKI編集部 高澤 翔汰

歴5年目(2024年8月以降から5年目です)のエンジニアです!
CMSでのサイト構築とWebデザイン制作を兼任して5年目になります。
自作のiOSアプリ(iPhoneアプリ)やWordPressプラグインを開発することもあり、まだまだ現在進行形で勉強中です!

お気軽に皆さんのご要望をお聞かせください!

どんなに些細なことでも構いません!よろしければ記事や当サイトへの「こんな記事があったら仕事とかで役に立つな〜」や「こうだったらもっと役に立つのに!」といったようなご要望等をお気軽にお聞かせください!今後のサービス改善にお役立てさせていただきます!

例1)Reactの技術記事を書いてほしい!
例2)WordPressの使い方とかを初心者向けに解説してほしい!...など

送信と同時にプライバシーポリシーに同意したものとします。