2026年6月2日

2026年6月2日

WordPressのウィジェットが表示されない・保存できない時の原因と直し方

WordPressのウィジェットの不具合は、「ウィジェット画面そのものがない」「保存できない」「テーマ変更で消えた」「自作ウィジェットでエラーになる」のどれかに分けると原因を絞り込めます。この記事では、2026年10月時点のWordPressで、症状ごとの原因と直し方を説明します。配置を戻したり設定を削除したりする前に、ウィジェットの設定を書き出す手順も紹介します。

症状と主な原因

症状 主な原因 対処の節
「外観」に「ウィジェット」がない ブロックテーマを使っている ウィジェット画面がない場合
保存できない・保存時にエラーが表示される REST APIの遮断、プラグインの競合、WAFによるブロック 保存できない場合
テーマを変えたらウィジェットが消えた 新しいテーマにウィジェットエリアのIDが合わない テーマ変更で消えた場合
管理画面に出るのにサイトに表示されない テンプレートで表示していない、IDの不一致 サイトに表示されない場合
自作ウィジェットで致命的エラー クラスの二重定義、メソッドの宣言が親クラスと合わない 自作ウィジェットのエラー

作業前にウィジェットの状態を確認する

WP-CLIが使える環境なら、まず現在の状態を確認します。

# 登録されているウィジェットエリア(サイドバー)の一覧
wp sidebar list --fields=name,id

# 特定のエリアに入っているウィジェット
wp widget list sidebar-1 --fields=name,id,position

# どのエリアにも置かれていない(使用停止中の)ウィジェット
wp widget list wp_inactive_widgets --fields=name,id

ウィジェットの配置は sidebars_widgets というオプションに、各ウィジェットの設定は widget_block(ブロックウィジェット)、widget_text(テキスト)のように widget_ で始まるオプションに保存されています。

バックアップを取る

配置を戻したり削除したりする前に、ウィジェットの設定を書き出しておきます。データベース全体のバックアップ(wp db export)でもかまいませんが、ウィジェットだけを書き出すと復元が簡単です。次の内容を export-widgets.php として保存し、WordPressのディレクトリで実行します。

<?php
// 使い方: wp eval-file export-widgets.php widgets-backup.json
global $wpdb;

$file = $args[0] ?? 'widgets-backup.json';

$names = $wpdb->get_col(
	$wpdb->prepare(
		"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE %s",
		$wpdb->esc_like( 'widget_' ) . '%'
	)
);

$data = array(
	'sidebars_widgets' => get_option( 'sidebars_widgets' ),
	'widgets'          => array(),
);
foreach ( $names as $name ) {
	$data['widgets'][ $name ] = get_option( $name );
}

file_put_contents( $file, wp_json_encode( $data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ) );
WP_CLI::success( sprintf( '%d 件のウィジェット設定を %s に書き出しました', count( $names ), $file ) );
wp eval-file export-widgets.php widgets-backup.json

元に戻すときは、次の import-widgets.php を使います。

<?php
// 使い方: wp eval-file import-widgets.php widgets-backup.json
$file = $args[0] ?? 'widgets-backup.json';

$data = json_decode( (string) file_get_contents( $file ), true );
if ( ! is_array( $data ) || ! isset( $data['sidebars_widgets'] ) ) {
	WP_CLI::error( "{$file} を読み込めませんでした" );
}

foreach ( $data['widgets'] as $name => $value ) {
	update_option( $name, $value );
}
update_option( 'sidebars_widgets', $data['sidebars_widgets'] );

WP_CLI::success( '復元しました。外観 → ウィジェットで配置を確認してください' );
wp eval-file import-widgets.php widgets-backup.json

この復元は、書き出したときと同じテーマ(同じウィジェットエリアのID)で使うことを想定しています。別のテーマに移す方法は後の節で説明します。

ウィジェット画面がない場合

「外観」メニューに「ウィジェット」が表示されないときは、ブロックテーマ(Twenty Twenty-Fiveなど、サイトエディターで編集するテーマ)を使っている可能性が高いです。ブロックテーマにはウィジェットエリアがなく、サイドバーやフッターの内容はサイトエディターでテンプレートパーツやブロックとして編集します。

クラシックテーマ(Twenty Twenty-Oneなど)を使っているのに表示されない場合は、テーマが register_sidebar() でウィジェットエリアを登録していません。次の「ウィジェットエリアを登録する」を参照してください。

保存できない場合

WordPress 5.8以降、クラシックテーマのウィジェット画面はブロックエディター(ブロックウィジェットエディター)になり、保存はREST API(/wp-json/wp/v2/widgets など)経由で行われます。保存できないときは、次の順に確認します。

  1. ブラウザの開発者ツールのネットワークタブを開いた状態で保存し、/wp-json/wp/v2/ へのリクエストが403や500になっていないか見ます。
  2. 403の場合は、セキュリティ系プラグインのREST API制限や、サーバーのWAF(ModSecurityなど)が遮断していることがあります。WAFは、HTMLやスクリプトを含むウィジェットの保存をブロックすることがあります。レンタルサーバーのWAFのログで確認します。
  3. 500の場合は、wp-content/debug.log(WP_DEBUG_LOG を有効にしている場合)や PHP のエラーログで原因のプラグインを特定します。
  4. 原因が分からない場合は、プラグインを一時的にすべて停止し、保存できるか試します(wp plugin deactivate --all で停止できますが、元に戻すために事前に wp plugin list --status=active --field=name の結果を控えてください)。

旧来のウィジェット画面に戻したい場合は、公式のClassic Widgetsプラグインを有効化するか、次のフィルターを使います。

<?php
// ブロックウィジェットエディターを無効にし、旧来のウィジェット画面に戻す
add_filter( 'use_widgets_block_editor', '__return_false' );

旧来の画面ではブロックを使ったウィジェットを編集できなくなるため、ブロック中心で運用している場合は原因の解消を優先してください。

テーマ変更で消えた場合

テーマを切り替えると、WordPressはウィジェットエリアのIDなどを手がかりに、配置を新しいテーマへ移し替えます。対応するエリアが見つからなかったウィジェットは削除されず、「使用停止中のウィジェット」に移ります。

管理画面では、「外観」→「ウィジェット」の「使用停止中のウィジェット」から、新しいテーマのエリアへ移動できます。WP-CLIでは次のように操作します。

# 使用停止中のウィジェットを確認
wp widget list wp_inactive_widgets --fields=name,id

# 新しいテーマのエリア(例: sidebar-1)へ移動。--position で並び順も指定できる
wp widget move text-2 --sidebar-id=sidebar-1
wp widget move block-5 --sidebar-id=sidebar-1 --position=1

テーマを作る側の対策としては、テーマ間でウィジェットエリアのIDをそろえておくと、切り替え時に配置が引き継がれやすくなります。

サイトに表示されない場合

ウィジェットエリアを登録する

ウィジェットエリアは、widgets_init フックで register_sidebar() を使って登録します。id はサイト内で重複しない英小文字の文字列にします。

<?php
add_action(
	'widgets_init',
	function () {
		register_sidebar(
			array(
				'name'          => 'メインサイドバー',
				'id'            => 'sidebar-main',
				'description'   => '投稿・固定ページのサイドバー',
				'before_widget' => '<section id="%1$s" class="widget %2$s">',
				'after_widget'  => '</section>',
				'before_title'  => '<h2 class="widget-title">',
				'after_title'   => '</h2>',
			)
		);
	}
);

テンプレートで表示する

登録しただけではサイトに表示されません。テーマのテンプレート(sidebar.php など)で dynamic_sidebar() を呼び出します。IDは register_sidebar() と同じものを指定します。

<?php if ( is_active_sidebar( 'sidebar-main' ) ) : ?>
	<aside id="secondary" class="widget-area">
		<?php dynamic_sidebar( 'sidebar-main' ); ?>
	</aside>
<?php endif; ?>

is_active_sidebar() は、エリアにウィジェットが1つもないと false を返します。管理画面では配置しているのに表示されない場合は、テンプレートとWP-CLIの wp sidebar list で、IDが一致しているか確認してください。

自作ウィジェットのエラー

「Cannot declare class」「Cannot redeclare」

Fatal error: Cannot declare class My_Custom_Widget, because the name is already in use は、同じ名前のクラスが2回定義されたときのエラーです(関数の場合は Cannot redeclare になります)。同じコードを functions.php とプラグインの両方に書いた、ファイルを2回読み込んだ、他のプラグインと名前が重なった、などが原因です。クラス名に独自の接頭辞を付け、class_exists() で囲むと防げます。

「must be compatible with WP_Widget::widget()」

WP_Widget を継承するとき、widget()・form()・update() の引数に array などの型を付けると、親クラスの宣言(型なし)と合わずに致命的エラーになります。

PHP Fatal error: Declaration of My_Custom_Widget::widget(array $args, array $instance): void must be compatible with WP_Widget::widget($args, $instance)

親クラスに合わせて、引数には型を付けずに書きます。次の例は、タイトルと本文を表示するウィジェットです。プラグイン(または wp-content/mu-plugins/ のファイル)に置きます。

<?php
/**
 * Plugin Name: My Custom Widget
 */

if ( ! class_exists( 'My_Custom_Widget' ) ) {
	class My_Custom_Widget extends WP_Widget {

		public function __construct() {
			parent::__construct(
				'my_custom_widget',
				'カスタムウィジェット',
				array( 'description' => 'タイトルと本文を表示するウィジェット' )
			);
		}

		// サイトでの表示(親クラスに合わせ、引数に型を付けない)
		public function widget( $args, $instance ) {
			$title   = apply_filters( 'widget_title', $instance['title'] ?? '', $instance, $this->id_base );
			$content = $instance['content'] ?? '';

			echo $args['before_widget'];
			if ( '' !== $title ) {
				echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
			}
			echo '<div class="widget-content">' . wp_kses_post( wpautop( $content ) ) . '</div>';
			echo $args['after_widget'];
		}

		// 管理画面の入力欄
		public function form( $instance ) {
			$title   = $instance['title'] ?? '';
			$content = $instance['content'] ?? '';
			?>
			<p>
				<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">タイトル:</label>
				<input class="widefat" type="text"
					id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
					name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
					value="<?php echo esc_attr( $title ); ?>">
			</p>
			<p>
				<label for="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>">本文:</label>
				<textarea class="widefat" rows="5"
					id="<?php echo esc_attr( $this->get_field_id( 'content' ) ); ?>"
					name="<?php echo esc_attr( $this->get_field_name( 'content' ) ); ?>"><?php echo esc_textarea( $content ); ?></textarea>
			</p>
			<?php
		}

		// 保存時の無害化
		public function update( $new_instance, $old_instance ) {
			return array(
				'title'   => sanitize_text_field( $new_instance['title'] ?? '' ),
				'content' => wp_kses_post( $new_instance['content'] ?? '' ),
			);
		}
	}
}

add_action(
	'widgets_init',
	function () {
		register_widget( 'My_Custom_Widget' );
	}
);

ブロックウィジェットエディターでは、自作ウィジェットは「レガシーウィジェット」ブロックから追加します。

widget_display_callback で表示を止める場合

widget_display_callback フィルターは、ウィジェットを表示する直前に設定(配列)を受け取ります。false を返すと、そのウィジェットは表示されません。このため、無名関数の戻り値を : array と宣言して false を返すと型エラーで止まります。戻り値の型は付けないか、array|false にします。

<?php
// ログインしていない訪問者には、ID が my_custom_widget-2 のウィジェットを表示しない
add_filter(
	'widget_display_callback',
	function ( $instance, $widget, $args ) {
		if ( 'my_custom_widget-2' === $widget->id && ! is_user_logged_in() ) {
			return false;
		}
		return $instance;
	},
	10,
	3
);

widget_types_to_hide_from_legacy_widget_block の意味

widget_types_to_hide_from_legacy_widget_block は、「レガシーウィジェット」ブロックの選択肢から隠すウィジェットの種類を指定するフィルターです(WordPress 5.8で追加)。許可リストではなく除外リストで、既定ではテキスト・カレンダー・最近の投稿など、同等のブロックがある標準ウィジェットが入っています。自作ウィジェットをここに追加すると、ブロックウィジェットエディターから追加できなくなるので注意してください。

まとめ

  • 「外観」に「ウィジェット」がないのは、多くの場合ブロックテーマを使っているため。サイトエディターで編集する
  • 状態の確認は wp sidebar list と wp widget list。配置は sidebars_widgets、設定は widget_ で始まるオプションにある
  • 削除や復元の前に、ウィジェットの設定を書き出す。sidebars_widgets をいきなり削除しない
  • 保存できないときは、REST APIへのリクエストのステータスを確認し、WAFやプラグインの遮断を疑う
  • テーマ変更で消えたウィジェットは「使用停止中のウィジェット」にある。wp widget move で新しいエリアへ移せる
  • 自作ウィジェットは、widget()・form()・update() の引数に型を付けない。クラス名には接頭辞を付け、class_exists() で囲む

ウィジェットの基本的な使い方はWordPressのウィジェット設定の基本、テーマ更新後にサイドバーが消えた場合はアップデート後にサイドバーが消えたときの対処法も参考にしてください。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲