カスタムフィールドを使用すると、ウェブサイトのコンテンツに追加の情報を割り当てることができます。この情報は、一般に「メタデータ」と呼ばれます。

「メタデータは「情報についての情報」であり、WordPressにおいては、投稿、ユーザー、コメント、タームに関する情報を意味します。

WordPressのメタデータは、「多対一」の関係にあり、選択肢には事実上、制限がない。好きなだけメタオプションを定義し、あらゆる情報を保存することができる」(英語原文の日本語訳)

Plugin Handbook

カスタムフィールドを使用して投稿に付与することのできるメタデータの例をいくつか見てみましょう。

  • 住所や不動産の地理的な座標値
  • イベントの日付
  • 書籍のISBNや著者名
  • 投稿者のその日の気分

等々、挙げたらきりがありません。

WordPressには、カスタムフィールドを容易に追加、管理できるデフォルトの機能はありません。クラシックエディターでのカスタムフィールドは、ページの一番下、投稿エディターの下に表示されます。

クラシックエディターのカスタムフィールド
クラシックエディターのカスタムフィールド

Gutenbergでは、カスタムフィールドはデフォルトで無効になっていますが、投稿設定で該当する項目を選択して表示することができます。

ブロックエディターでカスタムフィールドパネルを追加
ブロックエディターでカスタムフィールドパネルを追加

ただし、フロントエンドにメタデータを表示するには、プラグインまたはコーディングが必要になります。

一般ユーザーがすぐに利用できる優れたプラグインは、多数存在します。WordPressのカスタムフィールドをもっと活用したい、透過的にブロックエディターと統合したい、またはカスタムGutenbergブロックを使用して、WordPressウェブサイトのフロントエンドに表示したい、とお考えの上級者の方は、ぜひこの記事を最後までご覧ください。

Gutenbergクラシックエディターの両方でカスタムフィールドを使用するベストな方法は、クラシックエディターとGutenbergの両方に対応するプラグインを作ることです。

両方のエディターでカスタムフィールドを管理するプラグインの作成は、やや複雑になりますがご安心を。この記事で、その手順をできるだけわかりやすくご説明していきます。コンセプトを理解できれば、Gutenbergでカスタムメタフィールドを管理し、あらゆる種類のウェブサイトを構築するスキルが身につくはず。

注意)コンピュータにNode.jsの最新バージョンをインストールしてください。

以下の手順で進めていきます。

公式ツールcreate-blockでブロックプラグインを作成

まず最初に、ブロックタイプを登録するプラグインの作成に必要になる、すべてのファイルと依存関係を準備します。ブロックプラグインを使用すると、カスタムメタデータを管理、表示するカスタムブロックタイプを簡単に構築できます。

ブロックタイプを作成するには、公式のcreate-blockツールを使用します。create-blockツールの詳しい使い方はこちらをご覧ください。

コマンドラインツールを開き、WordPress開発サイトpluginsディレクトリに移動して、以下のコマンドを実行します。

npx @wordpress/create-block

プロンプトが表示されたら、次の情報を入力します。

  • The template variant to use for this block(ブロックに使用するテンプレートのバリエーション):dynamic
  • The block slug used for identification (also the output folder name)(識別に使用するブロックスラッグ、出力フォルダ名):metadata-block
  • The internal namespace for the block name (something unique for your products)(ブロック名の内部名前空間、プラグイン独自の名前):meta-fields
  • The display title for your block(ブロックの表示タイトル):Meta Fields
  • The short description for your block (optional)(ブロックの短い説明/任意):Block description
  • The dashicon to make it easier to identify your block (optional)(ブロックを識別するダッシュアイコン/任意):book
  • The category name to help users browse and discover your block(ブロックの閲覧や発見を助けるカテゴリ名):widgets
  • Do you want to customize the WordPress plugin?(WordPressプラグインをカスタマイズしますか?):Yes/No

上記の値は、以下に使用されます。

  • 識別に使用するブロックスラッグ─プラグインのフォルダ名テキストドメイン
  • ブロック名の内部名前空間─プラグインのコード全体で使用されるブロック内部名前空間関数プレフィックス
  • ブロックの表示タイトルプラグイン名とエディターインターフェースで使用されるブロック名

セットアップには、2~3分かかる場合があります。処理が完了すると、利用可能なコマンドの一覧が表示されます。

ブロックプラグインが作成されたことがわかる
ブロックプラグインが作成されたことがわかる

次のセクションに進む前に、コマンドラインツールでプラグインのフォルダに移動し、次のコマンドを実行します。

cd metadata-block
npm start

これでコードを実装する準備が整いました。次のステップでは、プラグインのメインPHPファイルを編集して、クラシックエディター用メタボックスを構築します。

その前に、Classic Editorプラグインをインストールし、有効化してください。

プラグイン画面を開いて、Meta Fieldsプラグインを有効化します。

プラグインの有効化
プラグインの有効化

クラシックエディターへのメタボックスの追加

クラシックエディターのメタボックスは、フォーム要素を保持するコンテナです。投稿者、タグ、カテゴリなど、特定の情報を入力することができます。

組み込みのメタボックスに加えて、プラグイン開発者は、カスタムメタボックスを好きなだけ追加できます。メタボックスには、プラグイン固有のデータを入力するHTMLフォーム要素(または任意のHTMLコンテンツ)を挿入します。

WordPress APIにはカスタムメタボックスを簡単に登録できる便利な機能があり、プラグインの動作に必要なすべてのHTML要素を挿入することができます。

まずは、作成したプラグインのPHPファイルに、以下のコードを追加してください。

// register meta box
function meta_fields_add_meta_box(){
	add_meta_box(
		'meta_fields_meta_box', 
		__( 'Book details' ), 
		'meta_fields_build_meta_box_callback', 
		'post',
		'side',
		'default'
	 );
}

// build meta box
function meta_fields_build_meta_box_callback( $post ){
	  wp_nonce_field( 'meta_fields_save_meta_box_data', 'meta_fields_meta_box_nonce' );
	  $title = get_post_meta( $post->ID, '_meta_fields_book_title', true );
	  $author = get_post_meta( $post->ID, '_meta_fields_book_author', true );
	  ?>
	  <div class="inside">
	  	  <p><strong>Title</strong></p>
		  <p><input type="text" id="meta_fields_book_title" name="meta_fields_book_title" value="<?php echo esc_attr( $title ); ?>" /></p>	
		  <p><strong>Author</strong></p>
		  <p><input type="text" id="meta_fields_book_author" name="meta_fields_book_author" value="<?php echo esc_attr( $author ); ?>" /></p>
	  </div>
	  <?php
}
add_action( 'add_meta_boxes', 'meta_fields_add_meta_box' );

add_meta_box関数はメタボックスを登録し、コールバック関数はメタボックスに挿入されるHTMLを構築します。これについては、今回は掘り下げませんが、気になる方は、WordPressのこのドキュメント、またはこちらのドキュメントを参照してください。また、この記事も参考になります。

次に、投稿者が入力したデータを、save_postフックがトリガーされた際に保存する関数を作成します(Developer Resourcesを参照)。

// save metadata
function meta_fields_save_meta_box_data( $post_id ) {
	if ( ! isset( $_POST['meta_fields_meta_box_nonce'] ) )
		return;
	if ( ! wp_verify_nonce( $_POST['meta_fields_meta_box_nonce'], 'meta_fields_save_meta_box_data' ) )
		return;
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
		return;
	if ( ! current_user_can( 'edit_post', $post_id ) )
		return;

	if ( ! isset( $_POST['meta_fields_book_title'] ) )
		return;
	if ( ! isset( $_POST['meta_fields_book_author'] ) )
		return;

	$title = sanitize_text_field( $_POST['meta_fields_book_title'] );
	$author = sanitize_text_field( $_POST['meta_fields_book_author'] );

	update_post_meta( $post_id, '_meta_fields_book_title', $title );
	update_post_meta( $post_id, '_meta_fields_book_author', $author );
}
add_action( 'save_post', 'meta_fields_save_meta_box_data' );

詳細については、オンラインドキュメントを参照してください。ここでは、メタキーの前にあるアンダースコア文字(_)についてだけ見ていきます。アンダースコア文字を付けると、WordPressに対して、デフォルトで利用可能なカスタムフィールド一覧から、このカスタムフィールドのキーを隠すように指示することができます。カスタムフィールドは、カスタムメタボックス内でのみ表示されます。

下の画像は、クラシックエディターで表示したカスタムメタボックスです。

クラシックエディターのカスタムメタボックス
クラシックエディターのカスタムメタボックス

ここでClassic Editorプラグインを無効にして、ブロックエディターでの見え方も確認します。メタボックスはまだ表示され、機能するものの、期待したものとはほど遠い状態。

この記事のテーマは、投稿記事やカスタム投稿タイプに添付されたメタデータを管理するシステムの作成と、ブロックエディター内での透過的な統合です。したがって上にご紹介したコードは、クラシックエディターとの後方互換性のためだけに必要になります。

次の手順に移る前に、add_meta_box関数に__back_compat_meta_boxフラグを追加して、ブロックエディターではカスタムメタボックスを削除するようにWordPressに通知します(メタボックス互換フラグ後方互換性も参照)。

メタボックスを登録するコールバック関数に戻り、以下のように変更します。

// register meta box
function meta_fields_add_meta_box(){
	add_meta_box(
		'meta_fields_meta_box', 
		__( 'Book details' ), 
		'meta_fields_build_meta_box_callback', 
		'post', 
		'side',
		'default',
		// hide the meta box in Gutenberg
		array('__back_compat_meta_box' => true)
	 );
}

プラグインファイルを保存して、WordPressの管理画面に戻りましょう。ブロックエディターには、カスタムメタボックスは表示されません。クラシックエディターを再度有効化すると、カスタムメタボックスが再び表示されます。

Gutenbergブロックエディターへのカスタムメタフィールドの追加(3つの選択肢)

Gutenbergのブロック開発に関する記事では、エディターの概要やパーツ、静的ブロックダイナミックブロックの開発について詳しくご説明しました。

前述したように、今回はさらに一歩踏み込んで、投稿記事にカスタムメタフィールドを追加する方法について見ていきます。

Gutenberg内で投稿のメタデータを保存、使用する方法は複数ありますが、今回は以下の3つを取り上げます。

カスタムメタフィールドを保存、表示するカスタムブロックの作成

はじめに、ダイナミックブロック内からカスタムメタフィールドを作成、管理する方法をご紹介します。ブロックエディターハンドブックによると、投稿メタフィールドは「投稿に関する追加データの保存に使用されるWordPressオブジェクト」です。まずはメタフィールドの新規登録が必要になります。

カスタムメタフィールドの登録

カスタムメタフィールドを登録する前に、使用する投稿タイプのカスタムフィールドのサポートの有無を確認します。また、カスタムメタフィールドを登録する際には、show_in_restパラメータをtrueに設定してください。

ではプラグインファイルに戻って、以下のコードを貼り付けます

/**
 * Register the custom meta fields
 */
function meta_fields_register_meta() {

    $metafields = [ '_meta_fields_book_title', '_meta_fields_book_author' ];

    foreach( $metafields as $metafield ){
        // Pass an empty string to register the meta key across all existing post types.
        register_post_meta( '', $metafield, array(
            'show_in_rest' => true,
            'type' => 'string',
            'single' => true,
            'sanitize_callback' => 'sanitize_text_field',
            'auth_callback' => function() { 
                return current_user_can( 'edit_posts' );
            }
        ));
    }  
}
add_action( 'init', 'meta_fields_register_meta' );

register_post_metaは、指定した投稿タイプに対してメタキーを登録します。上のコードでは、ウェブサイトに登録されている投稿タイプのうち、カスタムフィールドをサポートするすべての投稿タイプに対して、2つのカスタムメタフィールドを登録します。詳しくは関数リファレンスを参照してください。

完了したら、ブロックプラグインのsrc/index.jsファイルを開きます。

クライアント上でのブロックタイプの登録

wp-content/plugins/metadata-block/srcフォルダに移動し、index.jsファイルを開いてください。

import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import metadata from './block.json';

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

静的ブロックであればsave関数がありますが、ここではダイナミックブロックを導入したためsave関数はありません。フロントエンドに表示されるコンテンツは、PHPによって動的に生成されます。

ブロックタイプの構築

wp-content/plugins/metadata-block/srcフォルダに移動し、edit.jsファイルを開いてください。以下のようなコードがあります(コメントは削除)。

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p { ...useBlockProps() }>
			{ __( 'Meta Fields – hello from the editor!', 'metadata-block' ) }
		</p>
	);
}

ここにエディターでレンダリングされるブロックの生成コードを追加します。

まず最初のステップとして、ブロックの構築に必要なコンポーネントと関数をインポートします。以下は、すべての依存関係です。

import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, RichText } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';
import { TextControl, PanelBody, PanelRow } from '@wordpress/components';
import './editor.scss';

これまでの関連記事をご覧になっていれば、import宣言の多くはご存知のはず。以下は、その一例です。

import { useSelect } from '@wordpress/data';
import { useEntityProp } from '@wordpress/core-data';

依存関係をインポートすると、Edit()関数内のuseSelectuseEntityPropは次のようになります。

const postType = useSelect(
		( select ) => select( 'core/editor' ).getCurrentPostType(),
		[]
	);
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );

このコードでは、現在のpostType、メタフィールドのオブジェクト(meta)、それらを更新するセッター関数(setMeta)を取得します。

Edit()関数の現在のコードを以下のように置き換えてください。

export default function Edit() {
	const blockProps = useBlockProps();
	const postType = useSelect(
		( select ) => select( 'core/editor' ).getCurrentPostType(),
		[]
	);
	const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
	const bookTitle = meta[ '_meta_fields_book_title' ];
	const bookAuthor = meta[ '_meta_fields_book_author' ];
	const updateBookTitleMetaValue = ( newValue ) => {
		setMeta( { ...meta, _meta_fields_book_title: newValue } );
    };
	const updateBookAuthorMetaValue = ( newValue ) => {
		setMeta( { ...meta, _meta_fields_book_author: newValue } );
	};
return ( ... );
}
  • useSelectを使用して、現在の投稿タイプを取得する
  • useEntityPropは、メタフィールドの配列と、新しいメタ値を設定するセッター関数を返す
  • updateBookTitleMetaValueupdateBookAuthorMetaValueは、メタフィールドの値を保存する2つのイベントハンドラ

続いて、Edit()関数が返すJSX(JavaScript XML)コードを構築します。

export default function Edit() {
	...
	return (
		<>
			<InspectorControls>
				<PanelBody 
					title={ __( 'Book Details' )}
					initialOpen={true}
				>
					<PanelRow>
						<fieldset>
							<TextControl
								label={__( 'Book title' )}
								value={ bookTitle }
								onChange={ updateBookTitleMetaValue }
							/>
						</fieldset>
					</PanelRow>
					<PanelRow>
						<fieldset>
							<TextControl
								label={ __( 'Book author' ) }
								value={ bookAuthor }
								onChange={ updateBookAuthorMetaValue }
							/>
						</fieldset>
					</PanelRow>
				</PanelBody>
			</InspectorControls>
			<div { ...blockProps }>
				<RichText 
					tagName="h3"
					onChange={ updateBookTitleMetaValue }
					allowedFormats={ [ 'core/bold', 'core/italic' ] }
					value={ bookTitle }
					placeholder={ __( 'Write your text...' ) }
				/>
				<TextControl
					label="Book Author"
					value={ bookAuthor }
					onChange={ updateBookAuthorMetaValue }
				/>
			</div>
		</>
	);
}

RichTextコンポーネントは、contenteditable(コンテンツ編集可能)な入力を、TextControlは単純なテキストフィールドを提供します。

また、ブロックに含まれる2つのフォームコントロールの代わりに、入力フィールドを含むサイドバーパネルを作成しました。

ファイルを保存して、エディターに戻ります。ブロックインサーターからMeta Fieldsブロックを追加して、書籍のタイトルと著者を記入します。

2つのカスタムメタフィールドを含むカスタムブロック
2つのカスタムメタフィールドを含むカスタムブロック

ブロック内のフィールドの値を変更すると、サイドバーの対応するテキストフィールドの値も変更されます。

次に、フロントエンドでレンダリングされるHTMLを生成するPHPコードを作成します。

フロントエンドでのブロックの表示

コードエディターで再びメインのPHPファイルを開き、ブロックの出力を生成するコールバック関数を以下のように書き換えます。

function meta_fields_metadata_block_block_init() {
	register_block_type(
		__DIR__ . '/build',
		array(
			'render_callback' => 'meta_fields_metadata_block_render_callback',
		)
	);
}
add_action( 'init', 'meta_fields_metadata_block_block_init' );

function meta_fields_metadata_block_render_callback( $attributes, $content, $block ) {
	
	$book_title = get_post_meta( get_the_ID(), '_meta_fields_book_title', true );
	$book_author = get_post_meta( get_the_ID(), '_meta_fields_book_author', true );
    
	$output = "";

	if( ! empty( $book_title ) ){
		$output .= '<h3>' . esc_html( $book_title ) . '</h3>';
	}
	if( ! empty( $book_author ) ){
		$output .= '<p>' . __( 'Book author: ' ) . esc_html( $book_author ) . '</p>';
	}
	if( strlen( $output ) > 0 ){
		return '<div ' . get_block_wrapper_attributes() . '>' . $output . '</div>';
	} else {
		return '<div ' . get_block_wrapper_attributes() . '>' . '<strong>' . __( 'Sorry. No fields available here!' ) . '</strong>' . '</div>';
	}
}

このコードは非常にわかりやすく、まずget_post_metaを使用して、カスタムメタフィールドの値を取得します。次にこの値を使用して、ブロックコンテンツを構築します。最後にコールバック関数からブロックのHTMLを返します。

以上で、ブロックの準備が整いました。この例では意図的にできるだけシンプルなコードにしていますが、Gutenbergのネイティブコンポーネントを使用すると、より高度なブロックを構築して、WordPressのカスタムメタフィールドをフル活用することができます。

複数のメタフィールドを含むカスタムブロック
複数のメタフィールドを含むカスタムブロック

この例では、h3要素とp要素を使用してフロントエンド用のブロックを構築しました。

しかしデータは、これ以外の様々な方法で表示できます。次の例では、メタフィールドを単純な順序なしリストで表しています。

フロントエンド上のサンプルブロック
フロントエンド上のサンプルブロック

この例の完全なコードは、公開されたgistで参照できます。

ドキュメントサイドバーへのカスタムメタボックスの追加

2つ目の方法は、プラグインを使用してドキュメントサイドバーに設定パネルを生成し、投稿にカスタムメタフィールドを添付します。

上の手順とほぼ同じになりますが、メタデータを管理するブロックが必要ない点は異なります。ドキュメントサイドバーに、コントロールセットを含むパネルを生成するコンポーネントを作成します。手順は以下のとおりです。

  1. create-blockを使用して新しいブロックプラグインを作成する
  2. クラシックエディター用のカスタムメタボックスを登録する
  3. register_post_meta()関数を使用してメインのプラグインファイルにカスタムメタフィールドを登録する
  4. index.jsファイルでプラグインを登録する
  5. 組み込みのGutenbergコンポーネントを使用してコンポーネントを構築する

1. create-blockを使用して新しいブロックプラグインを作成する

新しいブロックプラグインを作成するには、前のセクションの手順に従います。新しいプラグインを作成するか、前の例で構築したスクリプトを編集してください。

2. クラシックエディター用のカスタムメタボックスを登録する

次に、まだクラシックエディターを使用しているWordPressウェブサイトとの後方互換性のため、カスタムメタボックスを登録します。手順は前のセクションで説明したものと同じです。

3. メインのプラグインファイルにカスタムメタフィールドを登録する

次の手順では、register_post_meta()関数を使用して、メインのプラグインファイルでカスタムメタフィールドを登録します。これも前の例に従ってください。

4. index.jsファイルでプラグインを登録する

ここまでの手順を終えたらindex.jsファイル内で、カスタムコンポーネントをレンダリングするプラグインを登録します。

プラグインを登録する前に、プラグインのsrcフォルダの中にcomponentsフォルダを作成してください。componentsフォルダの中に、新しくMetaBox.jsファイルを作成します。コンポーネントの名前は自由に付けてかまいません。ただし、Reactの命名に関するベストプラクティスに従ってください。

次に進む前に、コマンドラインツールから@wordpress/pluginsモジュールをインストールします。

プロセスを停止して(macの場合)、モジュールをインストールし、再びプロセスを開始します。

^C
npm install @wordpress/plugins --save
npm start

プラグインのindex.jsファイルを開き、以下のコードを貼り付けます。

/**
 * Registers a plugin for adding items to the Gutenberg Toolbar
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
 */
import { registerPlugin } from '@wordpress/plugins';

import MetaBox from './components/MetaBox';

これもわかりやすいコードですが、Reactに詳しくない方向けに、2つのimport文について少し触れておきます。

最初のimport文では、関数の名前を中括弧で囲んでいます。2つ目のimport文では、コンポーネントの名前を中括弧で囲んでいません。

次にプラグインを登録します。

registerPlugin( 'metadata-plugin', {
	render: MetaBox
} );

registerPluginは、単純にプラグインを登録します。この関数は2つのパラメータを取ります。

  • プラグインを識別する一意の文字列
  • プラグイン設定のオブジェクト(注意:renderプロパティは必須で、有効な関数でなければなりません)

5. 組み込みのGutenbergコンポーネントを使用してコンポーネントを構築する

これでReactコンポーネントを構築できます。MetaBox.jsファイル(またはコンポーネント用のファイル)を開き、以下のimport文を追加します。

import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { PanelRow, TextControl, DateTimePicker } from '@wordpress/components';

compose関数は関数合成を実行します。関数合成では、ある関数の結果が別の関数に渡されます。composeを使用する前に、対応するモジュールをインストールしてください。

npm install @wordpress/compose --save

compose関数の実際の例が、この後すぐに登場します。

  • withSelectwithDispatchは2つの高階コンポーネントで、それぞれ、WordPressストアからデータを取得、WordPressストアにデータを送信します。withSelectは、登録されたセレクタを使用してステート由来のpropsを挿入します。withDispatchは、登録されたAction Creatorを使用して、propsをディスパッチします。
  • PluginDocumentSettingPanelは、ドキュメントサイドバーの項目をレンダリングします(Githubのソースコードを参照してください)。

次に、ドキュメントサイドバーにメタボックスパネルを表示するコンポーネントを作成します。MetaBox.jsファイルに、次のコードを貼り付けてください。

const MetaBox = ( { postType, metaFields, setMetaFields } ) => {

	if ( 'post' !== postType ) return null;

	return(
		<PluginDocumentSettingPanel 
			title={ __( 'Book details' ) } 
			icon="book"
			initialOpen={ false }
		>
			<PanelRow>
				<TextControl 
					value={ metaFields._meta_fields_book_title }
					label={ __( "Title" ) }
					onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
				/>
			</PanelRow>
			<PanelRow>
				<TextControl 
					value={ metaFields._meta_fields_book_author }
					label={ __( "Author" ) }
					onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
				/>
			</PanelRow>
			<PanelRow>
				<TextControl 
					value={ metaFields._meta_fields_book_publisher }
					label={ __( "Publisher" ) }
					onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
				/>
			</PanelRow>
			<PanelRow>
				<DateTimePicker
					currentDate={ metaFields._meta_fields_book_date }
					onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
					__nextRemoveHelpButton
					__nextRemoveResetButton
				/>
			</PanelRow>
		</PluginDocumentSettingPanel>
	);
}

const applyWithSelect = withSelect( ( select ) => {
	return {
		metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
		postType: select( 'core/editor' ).getCurrentPostType()
	};
} );

const applyWithDispatch = withDispatch( ( dispatch ) => {
	return {
		setMetaFields ( newValue ) {
			dispatch('core/editor').editPost( { meta: newValue } )
		}
	}
} );

export default compose([
	applyWithSelect,
	applyWithDispatch
])(MetaBox);

このコードを掘り下げてみます。

  • PluginDocumentSettingPanel要素は、ドキュメントサイドバーに新しいパネルをレンダリングします。ここではタイトル「Book details」(書籍の詳細)とアイコンを設定し、initialOpenfalseに設定して、初期状態ではパネルを閉じています。
  • PluginDocumentSettingPanel内には、3つのテキストフィールドと、出版日の設定用にDateTimePicker要素を定義します。
  • withSelectを介したselect関数を利用して、metaFieldspostTypeを取得します。withDispatchを介したdispatch関数を利用して、メタデータの値を更新します。
  • 最後にcompose関数を使用して、コンポーネントをwithSelectおよびwithDispatchの高階コンポーネントと合成します。これにより、コンポーネントはmetaFieldspostTypeのプロパティとsetMetaFields関数を利用できます。

MetaBox.jsファイルを保存し、WordPress開発サイトで新しい投稿を作成し、ドキュメントサイドバーを確認してください。「Book details」(書籍の詳細)パネルが表示されます。

Gutenberg内のカスタムメタボックスパネル
Gutenberg内のカスタムメタボックスパネル

テストを実行し、カスタムメタフィールドに値を設定して投稿を保存します。ページを再読み込みして、入力した値が表示されることを確認しましょう。

次に、前のセクションで構築したブロックを追加して、すべてが正しく動作することを確認してください。

投稿のメタデータを管理するカスタムサイドバーの追加

投稿やカスタム投稿タイプに大量のカスタムメタフィールドを追加するには、プラグイン専用のカスタム設定サイドバーを作成します。

手順は上でご紹介した例とよく似ているため、Gutenberg用のカスタムサイドバーは簡単に構築可能です。

手順は以下のとおりです。

  1. create-blockを使用して新しいブロックプラグインを作成する
  2. クラシックエディター用のカスタムメタボックスを登録する
  3. register_post_meta()関数を使用してメインのプラグインファイルにカスタムメタフィールドを登録する
  4. index.jsファイルでプラグインを登録する
  5. 組み込みのGutenbergコンポーネントを使用してコンポーネントを構築する

1. create-blockを使用して新しいブロックプラグインを作成する

前に説明した手順に従い、ブロックプラグインを作成します。新規に作成するか、先ほど構築したスクリプトを編集してください。

2. クラシックエディター用のカスタムメタボックスを登録する

クラシックエディターを使用しているWordPressサイトとの後方互換性のため、カスタムメタボックスを登録します。手順は前のセクションでご説明した通り。

3. メインのプラグインファイルにカスタムメタフィールドを登録する

register_post_meta()関数を使用して、メインのプラグインファイルでカスタムメタフィールドを登録します。

4. index.jsファイルでプラグインを登録する

componentsフォルダに空のCustomSidebar.jsファイルを作成します。

作成したら、index.jsファイルを以下のように変更します。

/**
 * Registers a plugin for adding items to the Gutenberg Toolbar
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/slotfills/plugin-sidebar/
 */
import { registerPlugin } from '@wordpress/plugins';

import CustomSidebar from './components/CustomSidebar';
// import MetaBox from './components/MetaBox';

registerPlugin( 'metadata-block', {
    render: CustomSidebar
} );

上のコードでは、まずCustomSidebarコンポーネントをインポートしてから、新しいコンポーネントをレンダリングするよう、registerPlugin関数に指示します。

5. 組み込みのGutenbergコンポーネントを使用してコンポーネントを構築する

次に、CustomSidebar.jsファイルを開き、以下の依存関係を追加します。

import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-post';
import { PanelBody, PanelRow, TextControl, DateTimePicker } from '@wordpress/components';

新たに2つのコンポーネントがインポートされていることがわかります。

  • PluginSidebarは、Gutenbergツールバーにアイコンを追加し、クリックすると<PluginSidebar />要素でラップされたコンテンツを含むサイドバーを表示します(このコンポーネントはGitHubにドキュメントがあります)。
  • PluginSidebarMoreMenuItemは、「オプション」ドロップダウンの「プラグイン」の下にメニュー項目をレンダリングし、対応するPluginSidebarコンポーネントを有効化します(GitHubも参照してください)。

これでカスタムコンポーネントを構築できます。

const CustomSidebar = ( { postType, metaFields, setMetaFields } ) => {
        
    if ( 'post' !== postType ) return null;

    return (
        <>
            <PluginSidebarMoreMenuItem 
                target="metadata-sidebar" 
                icon="book"
            >
                Metadata Sidebar
            </PluginSidebarMoreMenuItem>
            <PluginSidebar 
                name="metadata-sidebar" 
                icon="book" 
                title="My Sidebar"
            >
                <PanelBody title="Book details" initialOpen={ true }>
                    <PanelRow>
                        <TextControl 
                            value={ metaFields._meta_fields_book_title }
                            label={ __( "Title" ) }
                            onChange={ (value) => setMetaFields( { _meta_fields_book_title: value } ) }
                        />
                    </PanelRow>
                    <PanelRow>
                        <TextControl 
                            value={ metaFields._meta_fields_book_author }
                            label={ __("Author", "textdomain") }
                            onChange={ (value) => setMetaFields( { _meta_fields_book_author: value } ) }
                        />
                    </PanelRow>
                    <PanelRow>
                        <TextControl 
                            value={ metaFields._meta_fields_book_publisher }
                            label={ __("Publisher", "textdomain") }
                            onChange={ (value) => setMetaFields( { _meta_fields_book_publisher: value } ) }
                        />
                    </PanelRow>
                    <PanelRow>
                        <DateTimePicker
                            currentDate={ metaFields._meta_fields_book_date }
                            onChange={ ( newDate ) => setMetaFields( { _meta_fields_book_date: newDate } ) }
                            __nextRemoveHelpButton
                            __nextRemoveResetButton
                        />
                    </PanelRow>
                </PanelBody>
            </PluginSidebar>
        </>
    )
}

最後のステップは、高階コンポーネントwithSelectwithDispatchとのコンポーネント合成です。

const applyWithSelect = withSelect( ( select ) => {
    return {
        metaFields: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
        postType: select( 'core/editor' ).getCurrentPostType()
    };
} );

const applyWithDispatch = withDispatch( ( dispatch ) => {
    return {
        setMetaFields ( newValue ) {
            dispatch('core/editor').editPost( { meta: newValue } )
        }
    }
} );

export default compose([
    applyWithSelect,
    applyWithDispatch
])(CustomSidebar);

変更を保存し、エディターインターフェースを確認します。「オプション」ドロップダウンを開くと、「プラグイン」セクションの下に新しい項目「Metadata Sidebar」が表示されます。この項目をクリックすると、新しいカスタムサイドバーが有効化されます。

PluginSidebarMoreMenuItemコンポーネントによって「プラグイン」セクション
PluginSidebarMoreMenuItemコンポーネントによって「プラグイン」セクション

の下にメニュー項目が追加されます

プラグイン設定サイドバー
プラグイン設定サイドバー

次に開発サイトに戻り、投稿を新規作成します。メタフィールドに値を入力し、エディターのキャンバスにブロックを追加すると、カスタムサイドバーに入力したメタ値と同じ値が表示されます。

投稿を保存して、フロントエンドでページをプレビューします。書籍のタイトル、著者、出版社、出版日を含むカードが表示されるはずです。

この記事で取り上げたすべてのコードは、公開gistで参照可能です。

さらなる学習

今回は、セレクタから高階コンポーネントまで、様々なトピックを取り上げました。記事中には参考にした主要リソースへのリンクも掲載しています。

各トピックをさらに深く掘り下げたい場合は、以下のリソースも参照してください。

GutenbergドキュメントとWordPress公式リソース

その他の公式リソース

コミュニティによるリソース

Kinstaの関連記事

まとめ

Gutenbergブロック開発にまつわる記事はこれが第三弾。今回は、上級者向けのテーマを取り上げました。これまでにご紹介した静的ブロック、そして動的ブロック開発より豊かになるはずです。

Gutenbergにおけるカスタムフィールドの可能性を活かして、高度で機能的なWordPressサイトを作成することができます。

また、ブロック開発に関する一連の記事で習得したスキルによって、WordPress以外でのReactコンポーネントの開発方法も理解できたのではないでしょうか。結局のところ、GutenbergもReactベースのSPA開発になります。

カスタムメタフィールドを使ったGutenbergブロックを作成したら、ぜひ以下のコメント欄で共有してください。

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.