2026年10月13日
2026年10月13日
ブロックエディターにサイドバーパネルを追加する方法|PluginDocumentSettingPanelとPluginSidebar
ブロックエディター(Gutenberg)では、投稿ごとの設定を、右側の設定サイドバーに自分のパネルとして追加できます。昔のクラシックエディターでメタボックスを作っていた用途は、多くがこの方法に置き換えられます。
この記事では、次の2つを1つのプラグインとして作ります。
- PluginDocumentSettingPanel: 「投稿」タブの中に、注目記事・読了時間・編集メモを入力するパネルを追加する(値は投稿のメタデータに保存)
- PluginSidebar: 上部のツールバーから開く独立したサイドバーに、題名と本文の文字数を表示する
2026年10月時点のWordPressと @wordpress/scripts を前提にしています。PluginSidebar などは WordPress 6.6 で @wordpress/edit-post から @wordpress/editor に移ったため、プラグインの動作条件を 6.6 以上にしています。コードは @wordpress/scripts 37.1.0 でビルドできることを確かめています。
できあがりのファイル構成
wpdr-editor-panel/
├── wpdr-editor-panel.php プラグイン本体(メタの登録とスクリプトの読み込み)
├── package.json
├── src/
│ ├── index.js 設定パネル(エントリーポイント)
│ └── sidebar.js 統計サイドバー
└── build/ npm run build で作られる
├── index.js
└── index.asset.php
手順1: ビルド環境を用意する
Node.js(LTS版)と npm を入れたパソコンで、wp-content/plugins の下にフォルダーを作ります。
cd wp-content/plugins
mkdir wpdr-editor-panel
cd wpdr-editor-panel
npm init -y
npm install --save-dev @wordpress/scripts
package.json の scripts を次のように書き換えます。
{
"scripts": {
"start": "wp-scripts start",
"build": "wp-scripts build"
}
}
wp-scripts は、既定で src/index.js を読み込んで build/index.js を作ります。同時に、スクリプトが使う WordPress のパッケージ(wp-plugins、wp-editor など)を並べた build/index.asset.php も作ります。@wordpress/editor などのパッケージは WordPress 本体のものを使うので、npm で個別に入れる必要はありません。
手順2: メタデータを登録してスクリプトを読み込む
wpdr-editor-panel.php を作ります。
<?php
/**
* Plugin Name: WPDR Editor Panel
* Description: ブロックエディターに記事の設定パネルと統計サイドバーを追加する
* Version: 1.0.0
* Requires at least: 6.6
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// メタデータを登録し、REST API(ブロックエディター)から読み書きできるようにする
add_action( 'init', function () {
$metas = array(
'_wpdr_is_featured' => array( 'type' => 'boolean', 'default' => false ),
'_wpdr_reading_time' => array( 'type' => 'integer', 'default' => 0 ),
'_wpdr_note' => array( 'type' => 'string', 'default' => '' ),
);
foreach ( $metas as $key => $args ) {
register_post_meta(
'post',
$key,
array(
'type' => $args['type'],
'default' => $args['default'],
'single' => true,
'show_in_rest' => true,
'auth_callback' => function ( $allowed, $meta_key, $post_id ) {
return current_user_can( 'edit_post', $post_id );
},
)
);
}
} );
// ブロックエディターでだけスクリプトを読み込む
add_action( 'enqueue_block_editor_assets', function () {
$asset_file = plugin_dir_path( __FILE__ ) . 'build/index.asset.php';
if ( ! file_exists( $asset_file ) ) {
return;
}
$asset = include $asset_file;
wp_enqueue_script(
'wpdr-editor-panel',
plugins_url( 'build/index.js', __FILE__ ),
$asset['dependencies'],
$asset['version'],
true
);
} );
ポイントは次のとおりです。
- ブロックエディターは REST API を通して投稿を読み書きするので、
show_in_restをtrueにしないと、JavaScript からメタを読めず、保存もされません - メタキーを
_で始めると「保護されたメタ」になり、カスタムフィールドの欄に表示されません。この場合、auth_callbackで編集を許可しないと REST API から書き込めません。ここでは、その投稿を編集できるユーザーに許可しています - 投稿タイプが
custom-fieldsをサポートしていないと、REST API にメタが出ません。標準の「投稿」はサポートしています。カスタム投稿タイプに使う場合はregister_post_type()のsupportsにcustom-fieldsを入れます typeは、保存時の値の検証に使われます。integerのメタに数字でない値を送ると、保存でエラーになります
enqueue_block_editor_assets はブロックエディターを開いたときにだけ実行されるので、サイトの表側には読み込まれません。
手順3: 設定パネルを作る(PluginDocumentSettingPanel)
src/index.js を作ります。
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/editor';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as editorStore } from '@wordpress/editor';
import {
TextareaControl,
ToggleControl,
TextControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import './sidebar';
function ArticleSettingsPanel() {
const { editPost } = useDispatch( editorStore );
const { postType, meta } = useSelect( ( select ) => {
const { getCurrentPostType, getEditedPostAttribute } =
select( editorStore );
return {
postType: getCurrentPostType(),
meta: getEditedPostAttribute( 'meta' ) || {},
};
}, [] );
// 投稿(post)の編集画面だけに表示する
if ( postType !== 'post' ) {
return null;
}
const updateMeta = ( key, value ) => {
editPost( { meta: { [ key ]: value } } );
};
return (
<PluginDocumentSettingPanel
name="wpdr-article-settings"
title={ __( '記事の詳細設定', 'wpdr-editor-panel' ) }
>
<ToggleControl
__nextHasNoMarginBottom
label={ __( '注目記事にする', 'wpdr-editor-panel' ) }
checked={ !! meta._wpdr_is_featured }
onChange={ ( value ) =>
updateMeta( '_wpdr_is_featured', value )
}
/>
<TextControl
__next40pxDefaultSize
__nextHasNoMarginBottom
label={ __( '読了時間(分)', 'wpdr-editor-panel' ) }
type="number"
min={ 0 }
value={ meta._wpdr_reading_time ?? 0 }
onChange={ ( value ) =>
updateMeta(
'_wpdr_reading_time',
parseInt( value, 10 ) || 0
)
}
/>
<TextareaControl
__nextHasNoMarginBottom
label={ __( '編集メモ(公開されません)', 'wpdr-editor-panel' ) }
value={ meta._wpdr_note ?? '' }
onChange={ ( value ) => updateMeta( '_wpdr_note', value ) }
rows={ 4 }
/>
</PluginDocumentSettingPanel>
);
}
registerPlugin( 'wpdr-article-settings', {
render: ArticleSettingsPanel,
} );
useSelectでエディターのストア(core/editor)から、編集中の投稿タイプとメタを読みます。getEditedPostAttribute( 'meta' )は、保存前の変更も含んだ値を返しますuseDispatchで取り出したeditPost()にメタを渡すと、エディター上の値が変わります。データベースに書き込まれるのは、「更新」や「公開」で投稿を保存したときです- 読了時間の欄は、空にしたときに
NaNを送らないよう、parseInt( value, 10 ) || 0で数値にしています __nextHasNoMarginBottomと__next40pxDefaultSizeは、コンポーネントの新しい余白と高さを使う指定です。付けないと、ブラウザのコンソールに非推奨の警告が出ることがあります
パネルは、設定サイドバーの「投稿」タブの中に表示されます。表示されない場合は、エディター右上の「︙」メニューの「設定」で、パネルの表示がオフになっていないか確認します。
手順4: 独立したサイドバーを作る(PluginSidebar)
src/sidebar.js を作ります。index.js の import './sidebar'; で読み込まれるので、ビルドの設定を変える必要はありません。
import { registerPlugin } from '@wordpress/plugins';
import {
PluginSidebar,
PluginSidebarMoreMenuItem,
store as editorStore,
} from '@wordpress/editor';
import { useSelect } from '@wordpress/data';
import { PanelBody, Notice } from '@wordpress/components';
import { count } from '@wordpress/wordcount';
import { __ } from '@wordpress/i18n';
function StatsSidebar() {
const { title, content } = useSelect( ( select ) => {
const { getEditedPostAttribute, getEditedPostContent } =
select( editorStore );
return {
title: getEditedPostAttribute( 'title' ) || '',
content: getEditedPostContent() || '',
};
}, [] );
const titleLength = title.length;
const chars = count( content, 'characters_excluding_spaces' );
return (
<>
<PluginSidebarMoreMenuItem target="wpdr-stats" icon="chart-bar">
{ __( '記事の統計', 'wpdr-editor-panel' ) }
</PluginSidebarMoreMenuItem>
<PluginSidebar
name="wpdr-stats"
title={ __( '記事の統計', 'wpdr-editor-panel' ) }
icon="chart-bar"
>
<PanelBody title={ __( 'タイトル', 'wpdr-editor-panel' ) }>
<p>
{ __( '文字数:', 'wpdr-editor-panel' ) } { titleLength }
</p>
{ titleLength > 60 && (
<Notice status="warning" isDismissible={ false }>
{ __(
'タイトルが60文字を超えています。',
'wpdr-editor-panel'
) }
</Notice>
) }
</PanelBody>
<PanelBody title={ __( '本文', 'wpdr-editor-panel' ) }>
<p>
{ __( '文字数(空白を除く):', 'wpdr-editor-panel' ) }{ ' ' }
{ chars }
</p>
</PanelBody>
</PluginSidebar>
</>
);
}
registerPlugin( 'wpdr-stats', {
render: StatsSidebar,
} );
PluginSidebarを登録すると、エディター上部のツールバーにアイコン(ここではchart-bar)が出て、クリックするとサイドバーが開きますPluginSidebarMoreMenuItemは、「︙」メニューにも同じサイドバーを開く項目を加えます。targetにはPluginSidebarのnameを指定します- 本文の文字数は、WordPress 本体の
@wordpress/wordcountで数えています。HTML タグを除いて数えるので、ブロックのコメントやタグが文字数に入りません。単語の区切りに空白を使わない日本語では、単語数ではなく文字数を使います
手順5: ビルドして有効化する
npm run build
build/index.js と build/index.asset.php ができたら、「プラグイン」画面で「WPDR Editor Panel」を有効化し、投稿の編集画面を開きます。開発中は npm run start を実行しておくと、ファイルを保存するたびに自動でビルドされます(ブラウザは再読み込みが必要です)。
本番サーバーに置くときは、build フォルダーと PHP ファイルがあれば動きます。node_modules はアップロードしなくてかまいません。
メタが保存されたか確かめる
投稿を保存したあと、WP-CLI で値を確認できます(123 は投稿ID)。
wp post meta get 123 _wpdr_reading_time
うまくいかないとき
| 症状 | 確認すること |
|---|---|
| パネルもサイドバーも表示されない | build/index.js があるか。ブラウザの開発者ツールのコンソールにエラーが出ていないか |
| WordPress 6.5 以前でコンソールにエラーが出る | 6.6 より古いと、@wordpress/editor に PluginSidebar などがない。WordPress を更新する |
| 入力しても保存されない | register_post_meta() の show_in_rest と auth_callback、投稿タイプの custom-fields サポートを確認する |
| 保存時にエラーが表示される | メタの type と送っている値の型が合っているか |
| 設定パネルが見当たらない | 「︙」メニューの「設定」で非表示になっていないか。投稿タイプが post 以外なら、コードの判定を変える |
まとめ
register_post_meta()でshow_in_restを有効にし、_で始まるキーにはauth_callbackを付けるenqueue_block_editor_assetsで、build/index.asset.phpの依存関係を使ってスクリプトを読み込む- 投稿の設定は
PluginDocumentSettingPanel、独立した画面はPluginSidebarを使い、どちらも@wordpress/editorから読み込む - 値は
useSelectで読み、useDispatch( editorStore ).editPost()で変更する。保存は投稿の保存と同時に行われる
関連記事: