2026年5月17日

2026年5月17日

WordPressのテーマサイドバーエラーを解決する方法

はじめに

WordPressでカスタムサイドバーを追加したのに管理画面のウィジェット設定に表示されない・dynamic_sidebar()を呼び出してもウィジェットが何も表示されない・サイドバーのウィジェットを設定したのにフロントエンドに出力されない・テーマをアップデートしたらサイドバーのウィジェットが全部リセットされてしまったといった問題は、WordPressのウィジェットエリア登録と呼び出しの仕組みを正しく理解することで解決できます。

症状・原因

  • register_sidebar()widgets_initフック外(例:直接functions.phpのトップレベル)で呼んでいるため、登録が遅すぎて無効になる
  • dynamic_sidebar()に渡すIDがregister_sidebar()idキーと一致していない
  • get_sidebar()をテンプレートファイルで呼んでいないためsidebar.phpが読み込まれない
  • ウィジェットエリアにウィジェットが1つも配置されていないためis_active_sidebar()falseを返す

解決手順

ステップ1:サイドバーエラーを診断する

# 登録済みサイドバー一覧を確認
wp eval "
global \$wp_registered_sidebars;
foreach (\$wp_registered_sidebars as \$id => \$sidebar) {
    echo \$id . ': ' . \$sidebar['name'] . PHP_EOL;
    echo '  アクティブ: ' . (is_active_sidebar(\$id) ? '✓ あり' : '× なし(ウィジェット未設定)') . PHP_EOL;
}
"

# sidebar.php ファイルが存在するか確認
wp eval "
\$files = ['sidebar.php', 'sidebar-left.php', 'sidebar-shop.php'];
foreach (\$files as \$f) {
    \$path = locate_template(\$f);
    echo \$f . ': ' . (\$path ? '✓ ' . \$path : '× なし') . PHP_EOL;
}
"

# ウィジェットが登録されているか確認
wp eval "
global \$wp_registered_widgets;
echo '登録済みウィジェット数: ' . count(\$wp_registered_widgets) . PHP_EOL;
"

# widgets_init フックが正しく動作しているか確認
wp eval "
\$priority = has_action('widgets_init', 'my_register_sidebars');
echo 'widgets_init フック: ' . (\$priority !== false ? '✓ 優先度' . \$priority : '× 未登録');
"

ステップ2:サイドバーを正しく登録する

// ✅ widgets_init フックで register_sidebar を呼ぶ
add_action('widgets_init', function(): void {
    // ✅ メインサイドバー
    register_sidebar([
        'name'          => 'メインサイドバー',
        'id'            => 'main-sidebar',     // ✅ dynamic_sidebar('main-sidebar') と一致
        'description'   => 'ブログ記事・固定ページのサイドバー',
        'before_widget' => '<section id="%1$s" class="widget %2$s">',
        'after_widget'  => '</section>',
        'before_title'  => '<h2 class="widget-title">',
        'after_title'   => '</h2>',
    ]);

    // ✅ ショップサイドバー
    register_sidebar([
        'name'          => 'ショップサイドバー',
        'id'            => 'shop-sidebar',
        'description'   => 'WooCommerce ショップページ専用',
        'before_widget' => '<div id="%1$s" class="widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ]);
});

// ✅ sidebar.php の基本構造
// sidebar.php:
<?php if (is_active_sidebar('main-sidebar')): ?>
<aside id="secondary" class="widget-area" role="complementary">
    <?php dynamic_sidebar('main-sidebar'); ?>
</aside>
<?php endif; ?>

// ✅ テンプレートファイルから呼び出す
<?php get_sidebar(); ?>           // sidebar.php を読み込む
<?php get_sidebar('shop'); ?>     // sidebar-shop.php を読み込む

ステップ3:条件に応じてサイドバーを切り替える

// ✅ ページによってサイドバーを動的に切り替える
function my_get_sidebar_id(): string {
    if (function_exists('is_shop') && (is_shop() || is_product_category() || is_product())) {
        return 'shop-sidebar';
    }
    if (is_singular('post')) {
        return 'blog-sidebar';
    }
    return 'main-sidebar';
}

// テンプレートで使用
$sidebar_id = my_get_sidebar_id();
if (is_active_sidebar($sidebar_id)) {
    echo '<aside class="widget-area">';
    dynamic_sidebar($sidebar_id);
    echo '</aside>';
}

// ✅ サイドバーなしのページテンプレート
// page-no-sidebar.php でサイドバーを表示しない
add_filter('body_class', function(array $classes): array {
    if (is_page_template('page-no-sidebar.php')) {
        $classes[] = 'no-sidebar';
        $classes[] = 'full-width';
    }
    return $classes;
});

// ✅ ウィジェットエリアのデフォルトウィジェットを設定
add_action('after_switch_theme', function(): void {
    // テーマ切り替え時にデフォルトウィジェットを設定
    $sidebars = get_option('sidebars_widgets', []);
    if (empty($sidebars['main-sidebar'])) {
        $sidebars['main-sidebar'] = ['search-2', 'recent-posts-2'];
        update_option('sidebars_widgets', $sidebars);
    }
});

ステップ4:カスタムウィジェットをサイドバーに追加する

// ✅ カスタムウィジェットを作成してサイドバーに追加
class My_Recent_Posts_Widget extends WP_Widget {
    public function __construct() {
        parent::__construct(
            'my_recent_posts',
            '最近の投稿(カスタム)',
            ['description' => 'カスタマイズされた最近の投稿ウィジェット']
        );
    }

    public function widget(array $args, array $instance): void {
        $title = apply_filters('widget_title', $instance['title'] ?? '最近の投稿');
        $count = absint($instance['count'] ?? 5);

        echo $args['before_widget'];
        if ($title) {
            echo $args['before_title'] . esc_html($title) . $args['after_title'];
        }

        $posts = get_posts(['numberposts' => $count, 'post_status' => 'publish']);
        if ($posts) {
            echo '<ul>';
            foreach ($posts as $post) {
                printf(
                    '<li><a href="%s">%s</a></li>',
                    esc_url(get_permalink($post->ID)),
                    esc_html($post->post_title)
                );
            }
            echo '</ul>';
        }
        echo $args['after_widget'];
    }

    public function update(array $new_instance, array $old_instance): array {
        return [
            'title' => sanitize_text_field($new_instance['title'] ?? ''),
            'count' => absint($new_instance['count'] ?? 5),
        ];
    }
}

add_action('widgets_init', fn() => register_widget('My_Recent_Posts_Widget'));

ステップ5:サイドバーのスティッキー化とパフォーマンス最適化

// ✅ サイドバーのキャッシュ(ウィジェット出力をTransientに保存)
function my_cached_sidebar(string $sidebar_id, int $ttl = 3600): void {
    $key    = 'sidebar_cache_' . $sidebar_id;
    $cached = get_transient($key);

    if ($cached !== false) {
        echo $cached; // phpcs:ignore WordPress.Security.EscapeOutput
        return;
    }

    ob_start();
    dynamic_sidebar($sidebar_id);
    $output = ob_get_clean();

    set_transient($key, $output, $ttl);
    echo $output; // phpcs:ignore WordPress.Security.EscapeOutput
}

// ✅ ウィジェット更新時にキャッシュを削除
add_action('update_option_sidebars_widgets', function(): void {
    global $wp_registered_sidebars;
    foreach (array_keys($wp_registered_sidebars) as $id) {
        delete_transient('sidebar_cache_' . $id);
    }
});

// ✅ スティッキーサイドバー用CSSをインラインで出力
add_action('wp_head', function(): void {
    if (!is_singular()) {
        return;
    }
    ?>
    <style>
    @media (min-width: 1024px) {
        .widget-area { position: sticky; top: 80px; }
    }
    </style>
    <?php
});

注意事項

  • register_sidebar()idパラメータは英数字とハイフンのみ使用できます。スペースや日本語を含む場合は自動的に変換されますが、意図しないIDになる可能性があるため必ず明示的に指定してください
  • テーマを切り替えると、以前のテーマで登録されていたサイドバーIDが変わるため、ウィジェットの割り当てが失われることがあります。テーマ移行時はsidebars_widgetsオプションをバックアップしてから作業してください

まとめ

WordPressのテーマサイドバーエラーの解決は①$wp_registered_sidebarsで登録確認・is_active_sidebar()でウィジェット有無確認・sidebar.phpファイルの存在確認、②widgets_initフックでregister_sidebar()iddynamic_sidebar()と一致・get_sidebar('name')でバリアント読み込み、③ページタイプ別にサイドバーIDを動的切り替え・body_classフィルターでサイドバーなしクラスを追加・テーマ切り替え時のデフォルト設定、④WP_Widget継承でカスタムウィジェット作成・widgets_initで登録・widget()/update()メソッドを実装、⑤ob_start()+Transientでウィジェット出力キャッシュ・update_option_sidebars_widgetsフックでキャッシュ削除・スティッキーサイドバーCSSの追加の手順で解決します。

お気軽にご相談ください

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