チュートリアル: はじめてのブロック作成

Topics

  • ここで作成するブロック
  • 準備
  • ブロックのひな型の作成
  • ファイルの確認
  • 初期セットアップ
    • block.json の更新
      • ブロックの説明の変更
      • ブロックサポートの追加
      • 不要なコードの削除
      • すべてをひとつに
    • index.js の更新
      • カスタムアイコンの追加
    • edit.js の更新
    • render.php の更新
    • クリーンアップ
  • ブロック属性の追加
    • block.json の更新
    • edit.js の更新
      • ユーザーインターフェースの追加
      • ブロックのコンテンツの更新
    • render.php の更新
  • 静的レンダリングの追加
    • 静的レンダリングを追加する理由
    • save 関数の追加
    • save.js の更新
    • 静的にレンダーされるブロック内の動的コンテンツの処理
      • 新しい属性の追加
      • edit.js での属性の設定
      • render.php の最適化
    • まとめ

このチュートリアルでは「Copyright Date ブロック」(著作権と年表示ブロック) を作成します。著作権シンボル (©)、現在の年、開始の年 (オプション) を表示する、基本的ながら実用的な、しばしばサイトのフッターでよく見かけるタイプのブロックです。

ここでは create-block パッケージを使用して、ブロックプラグインのひな形作成から各ファイルの修正まで、完全な手順を紹介します。このチュートリアルを実行するにあたっては WordPress の開発経験があると有益ですが、必須ではありません。

このチュートリアルを終えるとブロック開発の基礎を明確に理解し、自身の WordPress ブロック作成に必要なスキルを得られます。

ここで作成するブロック

このチュートリアルでは以下のようなブロックを作成します。

このチュートリアルで作成するブロック

WordPress Playground では完成したチュートリアルを試すことができます。また クイックスタートガイド を使用すると、ローカルの WordPress 環境に完全なブロックプラグインをインストールできます。

Top ↑

準備

このチュートリアルを実行するには、以下が必要です。

  1. コードエディター
  2. Node.js 開発ツール
  3. ローカル WordPress 環境

もしまだ準備できていなければ、ブロック開発環境のドキュメントを参照してください。セットアップが完了したら、ここに戻ってきてください。

このチュートリアルでは、wp-env を使用して WordPress のローカル開発環境を作成します。すでに好みのローカル開発ツールがあれば、自由にそのツールを使用してください。

Top ↑

ブロックのひな型の作成

Copyright Date ブロックを作成する最初のステップは、@wordpress/create-block パッケージを使用した、ブロックの初期構成のひな形の作成です。

このパッケージの使用方法については、create-block 入門 を参照してください。

コンピュータ上の任意のディレクトリ (フォルダ) から create-block を使用し、次に wp-env を使用すると、新しいブロックプラグインをインストールして有効化した、ローカルの WordPress 開発環境を作成できます。

まず、ブロックプラグインを置くディレクトリを選択するか、オプションで新しいフォルダ「Block Tutorial」を作成します。ターミナルを開き、このディレクトリに cd します。そして以下のコマンドを実行します。

wp-env を使用していなければ、代わりにターミナルを使用してローカルの WordPress インストール内の plugins/ フォルダに移動して、以下のコマンドを実行します。

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

このコマンドを実行すると、plugins フォルダ内に新しいディレクトリ copyright-date-blockが作成されます。このディレクトリには、ブロックのカスタマイズを始めるために必要なすべての初期ファイルが含まれています。

このコマンドはまた、copyright-date-block をスラッグとしてブロックの基本構成を設定します。このスラッグはWordPress 内で一意にブロックを識別します。

コマンドに --variant=dynamic フラグが指定されていることにお気づきかもしれません。これは create-block に対して動的にレンダーされるブロックのひな形を作成するよう伝えます。このチュートリアルの後半では、動的レンダリングと静的レンダリングについて学び、静的レンダリングをこのブロックに追加します。

WordPress 管理画面のプラグインページに移動し、プラグインが有効になっていることを確認してください。次に、新しいページまたは投稿を作成し、Copyright Date ブロックを挿入できることを確認してください。挿入すると以下のようになります。

エディター内でのひな形のブロック

Top ↑

ファイルの確認

ひな形のブロックを修正する前に、プラグインのファイルの構成を確認することが重要です。コードエディターでプラグインフォルダを開きます。

ブロックプラグインを構成するファイル

次に、ブロックのファイル構成を参照して、各ファイルが何をするのかの概要をざっと眺めてください。今すぐには理解できなくても構いません。このチュートリアルを通して、各ファイルの使い方を学びます。

動的ブロックのひな形を作成したため、save.js ファイルはありません。チュートリアルの後半で、このファイルをプラグインに追加して、静的レンダリングを有効化します。

Top ↑

初期セットアップ

できるだけシンプルな Copyright Date ブロックを作成するところから始めましょう。動的にレンダーされ、著作権記号 (©) と現在の年を表示するだけのブロックを作成します。いくつかのコントロールも追加して、ユーザーがフォントサイズとテキストの色を変更できるようにします。

次のステップに進む前に、ターミナルでプラグインディレクトリから npm run start を実行します。このコマンドは /src フォルダ内の各ファイルの変更を監視し、ファイルを保存するたびに、ブロックのビルドファイルを更新します。

詳細については、ブロックエディターでの JavaScript の利用を参照してください。

Top ↑

block.json の更新

/src フォルダ内の 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",
	"icon": "smiley",
	"description": "Example block scaffolded with Create Block tool.",
	"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 を参照してください。

ひな形作成のプロセスでこのファイルを作成したため、Copyright Date ブロックのニーズに合わせるには若干の更新が必要です。

Top ↑

ブロックの説明の変更

まずアイコンを削除し、より適切な説明を追加することから始めます。カスタムアイコンを後で追加します。

  1. "icon": 行を削除
  2. "description": の説明文を「Display your site’s copyright date.」(サイトの著作権と公開年を表示) で置換
  3. ファイルを保存

エディターを更新すると、ブロックからスマイルのアイコンが消え、説明文が更新されていることが確認できます。

エディター内の、情報が更新されたブロック

Top ↑

ブロックサポートの追加

次に、いくつかのブロックサポートを追加します。ユーザーはブロックのフォントサイズとテキスト色を自由に設定できるようになります。

カスタム機能の構築を検討する前に、常にネイティブのブロックサポートを使用してください。このアプローチにより、ユーザーはブロック間で一貫した編集体験を得られ、ブロックもわずか数行のコードでコア機能の恩恵を受けられます。

block.json ファイル内の supports セクションを以下のように更新します。

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

"text": true でテキスト色のサポートを有効にすると、デフォルトで背景色も有効になることに注意してください。そのままでも構いませんが、このチュートリアルでは必要ないため、"background": false を設定しています。

ファイルを保存し、エディターでブロックを選択します。これで、設定サイドバーに色とタイポグラフィの両方のパネルが表示されます。設定を変更して、変化の様子を見てみましょう。

エディター内の、block supports 付きブロック

Top ↑

不要なコードの削除

簡単のため、Copyright Date ブロックのすべてのスタイルは、ブロックサポートの color と typography で制御します。またこのブロックは、フロントエンドの JavaScript を持ちません。したがって block.json ファイル内で、スタイルシートや viewScript を指定する必要はありません。

  1. editorStyle 行を削除
  2. style 行を削除
  3. viewScript 行を削除
  4. ファイルを保存

エディターを更新すると、ブロックのスタイルが現在のテーマと一致していることがわかります。

エディター内の、デフォルトのスタイルのないブロック

Top ↑

すべてをひとつに

最終的に 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"
}

Top ↑

index.js の更新

ブロック自身の機能を作り始める前に、もう少しクリーンアップして、ブロックにカスタムアイコンを追加しましょう。

index.js ファイルを開いてください。これはブロックのメインの JavaScript ファイルで、クライアントでのブロックの登録に使用されます。クライアントサイドとサーバーサイドの登録については、ブロックの登録を参照してください。

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

import Edit from './edit';
import metadata from './block.json';

registerBlockType( metadata.name, {
	edit: Edit,
} );

デフォルトでは、オブジェクトは edit プロパティだけを含みますが、icon を含む多くのプロパティを追加できます。これらのプロパティのほとんどは既に block.json で定義されていますが、カスタム SVG を使用するにはここでアイコンを指定する必要があります。

Top ↑

カスタムアイコンの追加

Gutenberg Storybookのカレンダーアイコンを使用して、次のように関数に SVG を追加します。

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
} );

すべてのブロックのアイコンは24ピクセルの正方形でなければなりません。上の viewBox パラメータに注意してください。

index.js ファイルを保存し、エディターを更新します。デフォルトの代わりに、カレンダーアイコンが表示されます。

エディター内のブロックのカスタムアイコン

この時点でブロックのアイコンと説明は正しくなり、ブロックサポートによりフォントのサイズとテキストの色を変更できます。さて、いよいよブロックの実際の機能に移りましょう。

Top ↑

edit.js の更新

edit.js ファイルは、このブロックがどのように機能し、どのようにエディターに表示されるかを制御します。現在、ユーザーにはメッセージ「Copyright Date Block – hello from the editor!」が表示されます。これを変更しましょう。

ファイルを開き、Edit() 関数がデフォルトのメッセージを含む paragraph タグを返すことを確認してください。

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

このコードは実際よりも少し複雑に見えます。

  • useBlockProps() はブロックラッパー内に、エディターで必要とされるすべての CSS クラスとスタイルを出力します。これには、先に追加したブロックサポートの提供するスタイルも含まれます。
  • __() はテキスト文字列の国際化に使用されます。

ブロックラッパーのドキュメントでは、ブロックのマークアップラッパーに適切な属性を持たせる方法を紹介しています。

ところでこのブロックの主な目的は、著作権記号 (©) と現在の年の表示でした。そのためまず現在の年を文字列形式で取得する必要があります。以下のコードがこれを行います。

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

次に関数を更新して、正しい情報を表示します。

export default function Edit() {
	const currentYear = new Date().getFullYear().toString();

	return (
		<p { ...useBlockProps() }>© { currentYear }</p>
	);
}

edit.js ファイルを保存し、エディターを更新します。著作権マーク (©) と現在の年が表示されます。

正しいコンテンツを表示する、エディター内のブロック

Top ↑

render.php の更新

エディター上ではブロックは正しく動作していますが、フロントエンドではデフォルトのブロックメッセージが表示されたままです。これを修正するには render.php ファイルを開きます。以下のコードがあります。

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


エディター内での useBlockProps() 関数と同様に、get_block_wrapper_attributes() は、ブロックのラッパー 内に必要なすべての CSS クラスとスタイルを出力します。あとはコンテンツのみ、更新が必要です。

PHP で現在の年を取得するには、date( "Y" )を使用します。render.php は次のようになります。

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

ファイルを保存し、エディターとフロントエンドでブロックが正しく表示されることを確認します。

Top ↑

クリーンアップ

create-block パッケージを使用してブロックのひな形を作成すると、必要のないファイルが含まれる場合があります。このチュートリアルでも、ブロックはスタイルシートやフロントエンド JavaScipt を使用していませんので、以下の操作でプラグインの 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 ブロックを構築できました。しかし、これで終わりではありません。次のセクションでは、さらに機能を追加し、静的レンダリングを有効にします。

Top ↑

ブロック属性の追加

作成した Copyright Date ブロックは現在の年を表示していますが、開始の年も表示するにはどうすればよいでしょう ?

これから作成するもの

この機能のためには、ユーザーがブロックのどこかで公開年を入力する必要があります。また、表示のオンオフを切り替える機能も必要です。

さまざまな方法でこの機能を実装できますが、いずれの方法でもブロックの属性が必要です。属性は、ブロックのカスタムデータを保存し、ブロックのマークアップを変更できます。

この開始年を表示する機能を実現するには、開始年を保存する属性と、WordPress に開始年の表示の有無を伝える別の属性が必要です。

Top ↑

block.json の更新

ブロックの属性は通常、block.json ファイルで指定します。ファイルを開き、example プロパティの後に以下のセクションを追加してください。

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

属性を定義する際には type を指定しなければなりません。ここで showStartingYear は true か false のため boolean を設定しています。startingYear は単なる文字列です。

ファイルを保存したら、エディターに移ります。

Top ↑

edit.js の更新

edit.js ファイルを開きます。2つの作業を行う必要があります。

  • ユーザーが開始年を入力でき、機能のオンオフを切り替えられるユーザーインターフェースを追加し、これらの設定を属性として保存する。
  • 定義した属性に応じて、正しいコンテンツを表示するようにブロックを更新する。

Top ↑

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

このチュートリアルの前半ではブロックサポートを追加することで、自動的にブロックの設定サイドバーに、色とタイポグラフィのパネルを作成しました。InspectorControlsコンポーネントを使用すると、独自のカスタムパネルを作成できます。

Inspector コントロール

InspectorControls は @wordpress/block-editor パッケージに属しています。14行目にコンポーネント名を追加することで edit.js ファイルにインポートできます。変更後は以下のようになります。

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

次に、Edit 関数を更新して、現在のブロックの内容と、文字列「Testing」を含む InspectorControls コンポーネントを返します。適切な JSX 構文となるためにすべてを フラグメント (<></>) で囲みます。結果は以下のようになります。

export default function Edit() {
const currentYear = new Date().getFullYear().toString();

	return (
		<>
			<InspectorControls>
				Testing
			</InspectorControls>
			<p { ...useBlockProps() }>© { currentYear }</p>
		</>
	);
}

ファイルを保存し、エディターを更新します。ブロックを選択すると、設定サイドバーにメッセージ「Testing」が表示されるはずです。

設定サイドバーにメッセージが表示されている
コンポーネントとパネル

さらにいくつかのコアコンポーネントを使用して、カスタムパネルと開始年表示機能のユーザーインターフェイスを追加します。PanelBodyTextControlToggleControl を @wordpress/components パッケージからインポートします。

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

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

次に、メッセージ「Testing」を PanelBody コンポーネントでラップし、title パラメータに「Settings」を設定します。その他のパラメータオプションについては、コンポーネントのドキュメントを参照してください。

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>
		</>
	);
}

ファイルを保存し、エディターを更新します。新しい設定パネルが表示されるはずです。

設定サイドバーに表示されたカスタムパネル
Text コントロール

次のステップでは、メッセージ「Testing」を TextControl コンポーネントで置き換え、ユーザーが startingYear 属性を設定できるようにします。ただし、その前に Edit() 関数に2つのパラメータを含める必要があります。

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

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

Edit() 関数の先頭を次のように更新します。

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

Copyright Date ブロックに関連するすべての属性を見るには、Edit() 関数の先頭に console.log( attributes ); を追加します。この方法は、カスタムブロックを作成し、テストする際に便利な方法です。

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

  1. label プロパティに「Starting year」を設定する。
  2. value プロパティに属性 startingYear を設定する。
  3. onChange プロパティは、値が変更されるたびに startingYear 属性を更新する。

これらをまとめると、Edit() 関数は以下のようになります。

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
						label={ __(
							'Starting year',
							'copyright-date-block'
						) }
						value={ startingYear || '' }
						onChange={ ( value ) =>
							setAttributes( { startingYear: value } )
						}
					/>
				</PanelBody>
			</InspectorControls>
			<p { ...useBlockProps() }>© { currentYear }</p>
		</>
	);
}

value プロパティが値 startingYear || '' になっています。記号 || は、論理和演算子と呼ばれます。startingYear が空の場合に React で警告が出るのを防ぎます。詳しくは Controlled and uncontrolled components を参照してください。

ファイルを保存し、エディターを更新します。設定パネルにテキストフィールドが存在することを確認してください。また、開始年を追加し、ページを更新したときに値が保存されていることを確認してください。

設定サイドバーでの Starting Year フィールド編集の様子
Toggle コントロール

次に、開始年表示のオンオフを切り替えるトグルを追加します。これは showStartingYear 属性を設定する ToggleControl コンポーネントで行えます。このコンポーネントには以下が含まれます。

  1. label プロパティ。「Show starting year」を設定する。
  2. checked プロパティ。属性 showStartingYear を設定する。
  3. onChange プロパティ。トグルがチェックされるたびに showStartingYear 属性を更新する。

また「Starting year」テキスト入力を更新して、showStartingYear が true のときのみ表示されるようにします。これには && 論理演算子を使用します。

Edit()関数は以下のようになります。

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
							label={ __(
								'Starting year',
								'copyright-date-block'
							) }
							value={ startingYear || '' }
							onChange={ ( value ) =>
								setAttributes( { startingYear: value } )
							}
						/>
					) }
				</PanelBody>
			</InspectorControls>
			<p { ...useBlockProps() }>© { currentYear }</p>
		</>
	);
}

ファイルを保存し、エディターを更新します。トグルをクリックするとテキスト入力が表示され、ページを更新しても、トグルは有効なままです。

設定サイドバーの Staring Year トグルの編集の様子

Top ↑

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

ここまでで、開始年を追加し、関連するブロック属性を更新するユーザーインターフェースを作成しました。次に、エディターで実際にブロックのコンテンツを更新します。

新しい変数 displayDate を作ります。showStartingYear が true で、ユーザーが startingYear を指定していれば、displayDate に startingYear と currentYear を em ダッシュで区切って表示します。それ以外の場合は currentYear を表示します。

コードは以下のようになります。

let displayDate;

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

let で宣言した変数は、後で再割り当てされる可能性があることを意味します。const で宣言した変数は、決して変更されないことを意味します。このコードは const を使用して書き換えられますが、これは個人の好みの問題です。

あとは currentYear 変数の代わりに displayDate を使うようにブロックのコンテンツを更新するだけです。

Edit() 関数は以下のようになります。

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>
		</>
	);
}

ファイルを保存し、エディターを更新します。設定パネルで変更を加えると、ブロックのコンテンツが正しく更新されることを確認してください。

設定サイドバーの新しいフィールドによりブロックのコンテンツが更新される様子

Top ↑

render.php の更新

エディター側は完成しましたが、フロントエンドにはまだ開始年を表示する機能が追加されていません。render.php ファイルを更新して、これを修正します。

まず、変数 $display_date を追加して、上の Edit() 関数での実装を繰り返します。

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

render.php では3つの変数が公開されています。これを使用してブロックの出力をカスタマイズできます。

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

コードは以下のようになります。

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

あとは $current_year 変数の代わりに $display_date を使うようにブロックの内容を更新するだけです。

最終的な 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 のコアコンポーネント、カスタム属性を利用しています。追加の機能もあり、著作権と日付を表示するブロックとしては多くの場面で十分すぎる内容です。

しかし、次のセクションでは、ブロックに静的レンダリングを追加します。WordPress でブロックデータがどのように保存されるかを説明し、意図せずプラグインが無効になってしまった際の、フォールバックを実装します。

Top ↑

静的レンダリングの追加

ブロックは、動的レンダリング、静的レンダリング、またはその両方を利用できます。これまでに作成したブロックは、動的にレンダーされます。動的にレンダーされるブロックでは、ブロックのマークアップと関連した属性はデータベースに保存されますが、HTML 出力は保存されません。

静的にレンダーされるブロックは、常にブロックマークアップ、属性、出力をデータベース内に保存します。ブロックは2つを組み合わせ、静的な出力をデータベースに保存しながら、フロントエンドでさらに動的に拡張することもできます。

エディターからコードエディターに切り替えると、次のようになります。

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

これを段落ブロックのような静的にレンダーされるブロックと比較してみてください。

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

段落の HTML は投稿コンテンツに格納され、データベースに保存されます。

動的レンダリングと静的レンダリングについては、ブロック開発の基本原理を参照してください。ほとんどのブロックは動的または静的のどちらかでレンダーされますが、両方の方法を利用するブロックも作成できます。

Top ↑

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

動的にレンダーされるブロックに静的レンダリングを追加しても引き続き render.php ファイルがフロントエンドの出力を制御しますが、ブロックの HTML コンテンツはデータベースに保存されます。このことは、プラグインがサイトから削除されても、コンテンツが残ることを意味します。この Copyright Date ブロックの場合、コンテンツはカスタム HTML ブロックに戻り、簡単に段落ブロックに変換できます。

ブロックタイプが存在しなくなった際のエディターでのエラーメッセージ

すべての状況で必要ではありませんが、動的にレンダーされるブロックに静的レンダリングを追加すると、意図せずプラグインが無効化された場合にフォールバックとして役立ちます。

またブロックのマークアップが、ブロックパターンやテーマテンプレートに含まれている場合を考えます。Copyright Date ブロックをインストールしていない状態で、テーマをインストールしたり、パターンを使用すると、ブロックが利用できないという通知は表示されますが、コンテンツは表示されます。

静的レンダリングを追加することは、WordPress でブロックコンテンツがどのように保存され、レンダーされるかを調べる良い方法でもあります。

Top ↑

save 関数の追加

まず、新しいファイル save.js を src/ フォルダに追加します。このファイルに以下のコードを追加します。

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 ファイルと同じように見えます。追加の情報については、ブロックラッパーのドキュメントを参照してください。

次に、 index.js ファイルで、この save() 関数をインポートし、 registerBlockType() 関数に save プロパティを追加します。以下は更新したファイルの簡略版です。

import save from './save';

...

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

オブジェクトのプロパティを定義する際、プロパティ名と変数名が同じであれば、省略形のプロパティ名を使用できます。上のコードの save は save: save の意味です。

save.js と index.js の両方のファイルを保存し、エディターを更新します。以下のようになるはずです。

エディターのブロックバリデーションのエラーメッセージ

心配しないでください。想定内のエラーです。ブラウザでインスペクタを開くと、次のようなメッセージが表示されるはずです。

コンソールでのブロックバリデーションエラーメッセージ

このブロックバリデーションエラーは、save() 関数はブロックの内容を返すものの、以前に保存されたブロックが動的だったため、ブロックのマークアップに HTML が保存されていないために発生します。以下が現在のマークアップであることを思い出してください。

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

以降のステップで save() 関数を更新するたびに、このエラーが繰り返し表示されます。「ブロックのリカバリーを試行」をクリックして、ページを更新してください。

ブロックのリカバリーを実行した後、コードエディターを開くと、マークアップは以下のようになっています。

<!-- 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() 関数の出力は、投稿コンテンツの HTML と正確に一致しなければなりませんが、機能を追加するたびに同期は失われます。ブロックを完全に構築し終わったときにバリデーションエラーがなければ、それで大丈夫です。

Top ↑

save.js の更新

次に、save() 関数の出力を更新して、正しい内容を表示するようにします。まず、edit.js で使用したのと同じ方法を繰り返します。

  1. 関数に attributes パラメータを追加する
  2. 変数 showStartingYear と startingYear を定義する
  3. currentYear 変数を定義する
  4. currentYearshowStartingYearstartingYear の値に応じて displayDate 変数を定義する

結果は以下のようになります。

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>
	);
}

ファイルを保存し、エディターを更新します。「ブロックのリカバリーを試行」をクリックし、ページを更新します。コードエディターを確認すると、ブロックマークアップは次のようになっているはずです。

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

この時点で、すべてが完成したように見えます。ブロックのコンテンツはデータベースに HTML として保存され、フロントエンドの出力は動的にレンダーされます。しかし、まだ対処しなければならないことがいくつかあります。

2023年にブロックが追加されたページを、2024年に更新したいとします。フロントエンドは期待通りに更新されますが、エディターではブロックのバリデーションエラーが発生します。save() 関数は2024年であることを知っていますが、データベースに保存されたブロックのコンテンツは2023年のままのためです。

次のセクションでこれを修正します。

Top ↑

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

一般的に、静的にレンダーされるブロック内では動的なコンテンツは避けたいところです。これが、動的レンダリングを指すときに「動的」という言葉が使われる理由の一部です。

とはいえ、このチュートリアルでは両方のレンダリング方法を組み合わせており、年が変わったときにブロックバリデーションエラーを抑止するには、もう少しコードが必要です。

問題の根本は、save() 関数の中で currentYear 変数が動的に設定されていることです。本来であれば、関数内で静的な変数として設定すべきです。これを追加の属性で解決します。

Top ↑

新しい属性の追加

block.json ファイルを開き、新しい属性 fallbackCurrentYear を追加します。ファイルの attributes セクションは以下のようになります。

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

次に save.js ファイルを開き、currentYear の代わりに新しい 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() 関数には常に、仮に showStartingYear や startingYear が未定義であっても、返すコンテンツがありました。

著作権記号のみを返す代わりに、fallbackCurrentYear が設定されていなければ null を返す条件を追加しましょう。一般に不完全な HTML データを保存するよりも、何も保存しない方が優れます。

最終的な 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>
	);
}

block.json ファイルと save.js ファイルの両方を保存します。これ以上の変更はありません。

Top ↑

edit.js での属性の設定

save() 関数は新しい fallbackCurrentYear を使用するため、どこかで設定する必要があります。Edit() 関数を使いましょう。

edit.js ファイルを開き、まず fallbackCurrentYear 変数を Edit() 関数の先頭で、他の属性と一緒に定義します。次に、関数内での動きを確認します。

エディターでブロックがロードされると、currentYear 変数が定義されます。そして、この関数はこの変数を使ってブロックのコンテンツをを設定します。

次に、fallbackCurrentYear 属性がまだ設定されていなければ、ブロックがロードされたときにfallbackCurrentYear 属性に currentYear を設定します。

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

これで動作しますが、ブロックが初期化されたときにこのコードが一度だけ実行されるようにすることで改善できます。それには、useEffect React フックを使用します。このフックの使い方については、React のドキュメントを参照してください。

まず、以下のコードで useEffect をインポートします。

import { useEffect } from 'react';

次に、上の setAttribute() コードを useEffect でラップし、このコードを Edit() 関数の currentYear 定義の後に置きます。結果は以下のようになります。

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 属性はすぐに設定されます。この値は save() 関数で利用できるようになり、正しいブロックのコンテンツがブロックのバリデーションエラーなしで表示されます。

注意する点は、年が変わる場合です。Copyright Date ブロックが2023年にページに追加され、2024年に編集された場合、fallbackCurrentYear 属性は currentYear と一致せず、属性は自動的に 2024 に更新されます。これにより、save() 関数が返す HTML も更新されます。

ブロックのバリデーションエラーは発生しませんが、エディターはページに変更を検知し、更新を促します。

Top ↑

render.php の最適化

最後のステップは render.php ファイルの最適化です。currentYear 属性と fallbackCurrentYear 属性が同じであれば、ブロックのコンテンツを動的に作成する必要はありません。既にデータベースに保存されていて、$content 変数を通じて render.php ファイルで利用できます。

一方 currentYear と fallbackCurrentYear が一致しなければ、生成したコンテンツをレンダーするようにファイルを更新します。

$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 );

以上です。これで、動的レンダリングと静的レンダリングの両方を利用するブロックが完成しました。

Top ↑

まとめ

おめでとうございます。チュートリアルを完了し、オリジナルの Copyright Date ブロックを構築しました。このチュートリアルを通して、WordPress のブロック開発における確かな基礎を身につけ、自身のブロックを構築する準備が整いました。

最後にこのチュートリアルの完全なコードは、GitHub の Block Development Examples リポジトリにあります。

これからスキルを磨きたい方、より高度なプロジェクトに取り組みたい方、WordPress の最新トレンドを知りたい方には、以下の情報やサイトがブロック開発のスキルアップに役立ちます。

どんなエキスパートも、かつては初心者だったことを忘れないでください。学び続け、実験し続け、そして最も重要な教えとして、WordPress での構築を楽しんでください。

原文

最終更新日: