概要

ブロックエディタ以前は、カスタムメタボックスを使用してエディタを拡張していました。現在は、開発者により多くの力を与え、著者にとってより良い体験を提供する新しい拡張方法があります。エディタを使用する人々にとって、より統一された一貫した体験を作成するために、古いカスタムメタボックスをこれらの新しい方法のいずれかに移行することをお勧めします。

ブロックエディタは、ほとんどの既存のメタボックスをサポートしています。詳細については、下記の後方互換性セクションを参照してください。

エディタの外で投稿メタを操作することに興味がある場合は、サイドバーのチュートリアルをチェックしてください。

メタを保存するためにブロックを使用する

通常、ブロックはシリアライズされたブロックHTML内に属性値を保存します。ただし、属性値を投稿メタとして保存し、テンプレート内のどこでもプログラム的にアクセスできるブロックを作成することもできます。

このガイドでは、ユーザーに単一の値を求め、それを投稿メタに保存するブロックを作成する方法を示します。

始める前に

このガイドは、あなたがすでにWordPressプラグイン、投稿メタ、および基本的なJavaScriptに精通していることを前提としています。入門として、JavaScriptの始め方チュートリアルを確認してください。

このガイドでは、基本的なブロックを作成する手順を説明しますが、カスタムブロックの作成についてより深く理解するために、ブロック作成チュートリアルを通過することをお勧めします。

必要なもの:

  • WordPress開発環境、
  • 編集の準備が整った最小限のプラグイン
  • ビルドとエンキュー用のJavaScriptセットアップ

完全なメタブロックの例が利用可能で、セットアップの参考にできます。

ステップバイステップガイド

ステップ1: メタフィールドを登録する

投稿メタフィールドは、投稿に関する追加データを保存するために使用されるWordPressオブジェクトです。使用する前に、新しいメタフィールドを登録する必要があります。投稿メタについて詳しくは、投稿メタデータの管理を参照してください。

フィールドを登録する際は、show_in_restパラメータに注意してください。これにより、データがREST APIに含まれることが保証され、ブロックエディタがメタデータを読み込み、保存するために使用します。追加情報については、register_post_meta関数定義を参照してください。

さらに、投稿タイプはcustom-fieldsをサポートする必要があります。register_post_meta関数が機能するために

フィールドを登録するには、次のコードをPHPプラグインに追加します:

  1. <?php
  2. // register custom meta tag field
  3. function myguten_register_post_meta() {
  4. register_post_meta( 'post', 'myguten_meta_block_field', array(
  5. 'show_in_rest' => true,
  6. 'single' => true,
  7. 'type' => 'string',
  8. ) );
  9. }
  10. add_action( 'init', 'myguten_register_post_meta' );

ステップ2: メタブロックを追加する

前のステップでメタフィールドが登録されたので、次にユーザーにフィールド値を表示する新しいブロックを作成します。

フックuseEntityPropは、ブロックがメタ値を取得または変更するために使用できます。

次のコードをJavaScriptのsrc/index.jsに追加します:

  1. import { registerBlockType } from '@wordpress/blocks';
  2. import { TextControl } from '@wordpress/components';
  3. import { useSelect } from '@wordpress/data';
  4. import { useEntityProp } from '@wordpress/core-data';
  5. import { useBlockProps } from '@wordpress/block-editor';
  6. registerBlockType( 'myguten/meta-block', {
  7. edit: ( { setAttributes, attributes } ) => {
  8. const blockProps = useBlockProps();
  9. const postType = useSelect(
  10. ( select ) => select( 'core/editor' ).getCurrentPostType(),
  11. []
  12. );
  13. const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
  14. const metaFieldValue = meta[ 'myguten_meta_block_field' ];
  15. const updateMetaValue = ( newValue ) => {
  16. setMeta( { ...meta, myguten_meta_block_field: newValue } );
  17. };
  18. return (
  19. <div { ...blockProps }>
  20. <TextControl
  21. label="Meta Block Field"
  22. value={ metaFieldValue }
  23. onChange={ updateMetaValue }
  24. />
  25. </div>
  26. );
  27. },
  28. // No information saved to the block.
  29. // Data is saved to post meta via the hook.
  30. save: () => {
  31. return null;
  32. },
  33. } );

投稿を作成し、メタブロックを追加してこれが機能することを確認します。値を入力できるフィールドが表示されます。投稿をドラフトまたは公開として保存すると、投稿メタ値も保存されます。ドラフトを保存して再読み込みすることで確認できます。フォームは再読み込み時にまだ入力されています。

データが保存されていることを確認するには、データベーステーブルwp_postmetaをチェックし、新しい投稿IDが新しいフィールドデータを含んでいることを確認できます。

トラブルシューティング: 変更の間にコードをビルドすることを忘れないでください。ステップ1からPHPコードを更新し、JavaScriptファイルがエンキューされていることを確認してください。ビルド出力と開発者コンソールでエラーを確認してください。

ステップ3: 投稿メタデータを使用する

最後のステップで保存された投稿メタデータを複数の方法で使用できます。

PHPで投稿メタを使用する

最初の例では、投稿メタフィールドの値を使用し、H4タグでラップされた投稿コンテンツの末尾に追加します。

  1. function myguten_content_filter( $content ) {
  2. $value = get_post_meta( get_the_ID(), 'myguten_meta_block_field', true );
  3. if ( $value ) {
  4. return sprintf( "%s <h4> %s </h4>", $content, esc_html( $value ) );
  5. } else {
  6. return $content;
  7. }
  8. }
  9. add_filter( 'the_content', 'myguten_content_filter' );

ブロック内で投稿メタを使用する

他のブロック内でも投稿メタデータを使用できます。この例では、データは各段落ブロックがレンダリングされるときに読み込まれ、つまりユーザーに表示されます。必要に応じて、これを任意のコアまたはカスタムブロックタイプに置き換えることができます。

PHPでは、register_block_type関数を使用して、ブロックがレンダリングされるときにメタ値を含めるためのコールバックを設定します。

  1. function myguten_render_paragraph( $block_attributes, $content ) {
  2. $value = get_post_meta( get_the_ID(), 'myguten_meta_block_field', true );
  3. // check value is set before outputting
  4. if ( $value ) {
  5. return sprintf( "%s (%s)", $content, esc_html( $value ) );
  6. } else {
  7. return $content;
  8. }
  9. }
  10. register_block_type( 'core/paragraph', array(
  11. 'api_version' => 3,
  12. 'render_callback' => 'myguten_render_paragraph',
  13. ) );

ステップ4: ブロックテンプレートを使用する(オプション)

メタブロックを使用する際の1つの問題は、著者が忘れやすいことです。なぜなら、各投稿に追加する必要があるからです。これを解決するために、ブロックテンプレートを使用します。ブロックテンプレートは、投稿タイプごとのブロックアイテムの事前定義されたリストです。テンプレートを使用すると、投稿タイプのデフォルトの初期状態を指定できます。

この例では、テンプレートを使用して投稿の先頭にメタブロックを自動的に挿入します。

次のコードをmyguten-meta-block.phpファイルに追加します:

  1. function myguten_register_template() {
  2. $post_type_object = get_post_type_object( 'post' );
  3. $post_type_object->template = array(
  4. array( 'myguten/meta-block' ),
  5. );
  6. }
  7. add_action( 'init', 'myguten_register_template' );

配列に他のブロックタイプを追加することもできます。プレースホルダーを含めたり、特定のブロックのセットに投稿をロックしたりすることもできます。テンプレートは、編集体験を制御するための強力なツールです。詳細については、上記のドキュメントを参照してください。

結論

このガイドでは、ブロックを使用して投稿メタを読み書きする方法を示しました。既存のメタボックスとの後方互換性については、下記のセクションを参照してください。

後方互換性

既存のメタボックスのテスト、変換、および維持

メタボックスをブロックに変換する前に、メタボックスがブロックエディタで機能するかどうかをテストする方が簡単な場合があります。明示的にそのようにマークします。

メタボックスがブロックエディタで機能しない場合、正しく機能するように更新することができない場合、次のステップはメタボックス宣言にblock_editor_compatible_meta_box引数を追加することです:

  1. add_meta_box( 'my-meta-box', 'My Meta Box', 'my_meta_box_callback',
  2. null, 'normal', 'high',
  3. array(
  4. '__block_editor_compatible_meta_box' => false,
  5. )
  6. );

WordPressはメタボックスを表示せず、ブロックエディタと互換性がないことを示すメッセージを表示します。これには、Classic Editorプラグインへのリンクが含まれます。デフォルトでは、block_editor_compatible_meta_boxtrueです。

メタボックスがブロックに変換された後、後方互換性のために既存として宣言できます:

  1. add_meta_box( 'my-meta-box', 'My Meta Box', 'my_meta_box_callback',
  2. null, 'normal', 'high',
  3. array(
  4. '__back_compat_meta_box' => true,
  5. )
  6. );

ブロックエディタが使用されると、このメタボックスはメタボックスエリアに表示されなくなります。これは、もはや後方互換性の目的でのみ存在するからです。クラシックエディタでは以前のように表示されます。

メタボックスデータ収集

各ブロックエディタページの読み込み時に、メタボックスデータを収集してエリアが空であるかどうかを判断するアクションを登録します。メタボックスデータの収集時に元のグローバル状態がリセットされます。

register_and_do_post_meta_boxesを参照してください。

これは、post.phpがメタボックスを登録するために実行する関数とフックを通過します。すなわち、add_meta_boxesadd_meta_boxes_{$post->post_type}、およびdo_meta_boxesです。

メタボックスは、コアメタボックス、標準カスタムタクソノミーメタボックス、および後方互換性の目的でのみ存在すると宣言されたメタボックスを除外するようにフィルタリングされます。

次に、この特定のタイプのメタボックスの各場所がアクティブかどうかを確認します。空でない場合はtrueの値が保存され、空である場合はfalseの値が保存されます。このメタボックスの場所データは、INITIALIZE_META_BOX_STATEのエディタReduxストアによってディスパッチされます。

理想的には、これをエディタのインスタンス化時に行い、このフローを簡素化することができます。ただし、admin_enqueue_scriptsの前にメタボックスの状態を知ることはできません。initializeEditor()を呼び出しています。このままで大丈夫ですが、initializeEditor()をフッターで発火させるか、admin_headの後のいずれかの時点で移動したい場合は、最近のエディタのブートストラップの変更により、これが可能になるかもしれません。ACFでテストして確認してください。

ReduxとReactメタボックス管理

ブロックエディタをレンダリングする際、メタボックスは隠しdiv #metaboxesにレンダリングされます。

Reduxストアは、すべてのメタボックスをデフォルトで非アクティブとして保持します。

  1. #### MetaBoxAreaコンポーネント
  2. コンポーネントがレンダリングされると、メタボックスコンテナへの参照を保存し、プレフェッチ位置からメタボックスHTMLを取得します。
  3. 投稿が更新されると、アクティブなメタボックスエリアのみが送信されます。これにより、不必要なリクエストが防止されます。メタボックスの送信によって追加のリビジョンは作成されません。アクティブなメタボックスに対して、`````REQUEST_POST_UPDATE`````Reduxアクションがトリガーされます。`````editor/effects.js`````を参照してください。`````REQUEST_META_BOX_UPDATES`````アクションは、そのメタボックスの状態を`````isUpdating`````に設定します。`````isUpdating`````プロパティは`````MetaBoxArea`````に送信され、フォーム送信を引き起こします。
  4. メタボックスエリアが保存されるとき、保存が進行中の間にユーザーがフォーム値を変更できないように、更新オーバーレイを表示します。
  5. 保存URLの例は次のようになります:
  6. `````example.org/wp-admin/post.php?post=1&action=edit&meta-box-loader=1

このURLは、_wpMetaBoxUrlグローバル変数を介してReactに自動的に渡されます。

このページはpost.php投稿フォームを模倣しているため、送信されると、すべての通常のフックとアクションが発火し、PHPメタボックスの処理を正しく行うための適切なグローバル状態を持ちます。成功した送信後、Reactは更新オーバーレイを削除するためのhandleMetaBoxReloadを信号します。

一般的な互換性の問題

ほとんどのPHPメタボックスはブロックエディタで引き続き機能するはずですが、高度な機能を含む一部のメタボックスは壊れる可能性があります。ブロックエディタでメタボックスが期待通りに機能しない一般的な理由は次のとおりです:

  • 投稿タイトル、投稿コンテンツフィールド、および他のメタボックス(古いエディタ)のターゲットとなるセレクタに依存するプラグイン。
  • TinyMCEのAPIに依存するプラグイン。ブロックエディタでは、単一のTinyMCEインスタンスと対話することができなくなりました。
  • “送信”または“保存”時にDOMを更新するプラグイン。

プラグインがページ上でPHPの警告や通知をトリガーする場合、これはHTML文書タイプ(<!DOCTYPE html>)が正しく出力されない原因となります。これにより、ブラウザは「Quirks Mode」を使用してレンダリングします。これは、ブラウザが解析している文書のタイプを知らないときに有効になる互換性レイヤーです。ブロックエディタはこのモードで機能することを意図していませんが、正常に機能しているように見えることがあります。メタボックスがエディタを覆っている、または他のレイアウトの問題が発生する場合は、文書の生のページソースを確認して、文書タイプ定義がページの最初に出力されていることを確認してください。JavaScriptコンソールにも、問題を示す警告が表示されます。

追加リソース