2026年5月25日

2026年5月25日

WordPressでウィジェットをカスタマイズする方法・独自ウィジェット作成手順

はじめに

「サイドバーに独自コンテンツを表示したい」「管理画面から設定できるウィジェットを自作したい」——WordPressのWP_Widgetクラスを継承することで、設定フォーム付きのカスタムウィジェットを作成できます。

症状・原因

標準ウィジェット(テキスト・画像・カテゴリー等)では要件を満たせない場合、WP_Widgetクラスを継承してカスタムウィジェットを実装します。WordPress 5.8以降はブロックウィジェットが導入されましたが、WP_Widgetベースのウィジェットも引き続き使用できます。

解決手順

ステップ1:ウィジェットエリア(サイドバー)を登録する

// functions.phpにウィジェットエリアを登録
add_action( 'widgets_init', function() {
    register_sidebar( [
        'id'            => 'main-sidebar',
        'name'          => 'メインサイドバー',
        'description'   => '記事ページの右側に表示されます。',
        'before_widget' => '<div id="%1$s" class="widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h3 class="widget-title">',
        'after_title'   => '</h3>',
    ] );

    register_sidebar( [
        'id'          => 'footer-widgets',
        'name'        => 'フッターウィジェット',
        'before_widget' => '<div class="footer-widget %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h4>',
        'after_title'   => '</h4>',
    ] );
} );
// テンプレートファイルでウィジェットエリアを表示
if ( is_active_sidebar( 'main-sidebar' ) ) {
    echo '<aside class="sidebar">';
    dynamic_sidebar( 'main-sidebar' );
    echo '</aside>';
}

ステップ2:カスタムウィジェットを作成する

// WP_Widgetクラスを継承したカスタムウィジェット
class My_Recent_Posts_Widget extends WP_Widget {

    public function __construct() {
        parent::__construct(
            'my_recent_posts',        // ウィジェットID
            '最新記事(カスタム)',    // ウィジェット名
            [ 'description' => 'カスタマイズされた最新記事ウィジェット' ]
        );
    }

    // フロントエンド表示
    public function widget( $args, $instance ) {
        $title     = apply_filters( 'widget_title', $instance['title'] ?? '' );
        $post_count = absint( $instance['post_count'] ?? 5 );

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

        $posts = get_posts( [
            'numberposts' => $post_count,
            'post_status' => 'publish',
        ] );

        echo '<ul class="recent-posts-list">';
        foreach ( $posts as $post ) {
            echo '<li><a href="' . get_permalink( $post ) . '">'
                . esc_html( get_the_title( $post ) ) . '</a></li>';
        }
        echo '</ul>';
        echo $args['after_widget'];
    }

    // 管理画面フォーム
    public function form( $instance ) {
        $title      = $instance['title'] ?? '最新記事';
        $post_count = $instance['post_count'] ?? 5;
        ?>
        <p>
            <label for="<?php echo $this->get_field_id( 'title' ); ?>">タイトル:</label>
            <input type="text" id="<?php echo $this->get_field_id( 'title' ); ?>"
                name="<?php echo $this->get_field_name( 'title' ); ?>"
                value="<?php echo esc_attr( $title ); ?>" class="widefat">
        </p>
        <p>
            <label for="<?php echo $this->get_field_id( 'post_count' ); ?>">表示件数:</label>
            <input type="number" id="<?php echo $this->get_field_id( 'post_count' ); ?>"
                name="<?php echo $this->get_field_name( 'post_count' ); ?>"
                value="<?php echo absint( $post_count ); ?>" min="1" max="20" class="widefat">
        </p>
        <?php
    }

    // 保存処理
    public function update( $new_instance, $old_instance ) {
        return [
            'title'      => sanitize_text_field( $new_instance['title'] ),
            'post_count' => absint( $new_instance['post_count'] ),
        ];
    }
}

// ウィジェットを登録
add_action( 'widgets_init', function() {
    register_widget( 'My_Recent_Posts_Widget' );
} );

ステップ3:ショートコードをウィジェットで使えるようにする

// テキストウィジェット内でショートコードを有効化
add_filter( 'widget_text', 'do_shortcode' );

// カスタムウィジェットでもショートコードを処理
// widget()メソッド内での使い方:
// echo do_shortcode( $instance['content'] ?? '' );

ステップ4:WP-CLIでウィジェットを管理する

# ウィジェットエリア一覧を表示
wp sidebar list

# サイドバーに登録されているウィジェット一覧
wp widget list main-sidebar

# テキストウィジェットをサイドバーに追加
wp widget add text main-sidebar --title="お知らせ" --text="本日は〇〇です"

# ウィジェットを削除
wp widget delete main-sidebar-1

# ウィジェットを別のサイドバーに移動
wp widget move main-sidebar-1 --sidebar-id=footer-widgets

ステップ5:ブロックウィジェットエリアに対応する

// WordPress 5.8以降: ブロックウィジェット編集を無効化(従来UIに戻す)
add_filter( 'gutenberg_use_widgets_block_editor', '__return_false' );
add_filter( 'use_widgets_block_editor', '__return_false' );

// ブロックウィジェット対応のサイドバーを登録(デフォルトで対応済み)
// register_sidebar() はブロックウィジェットと互換性があります

// カスタムウィジェットをブロックに変換する場合
// → wp_widget_description() でブロック化を案内

注意事項

  • WordPress 5.8以降、デフォルトのウィジェット編集UIがブロックエディターに変わりました。従来のウィジェット管理UIに戻すにはuse_widgets_block_editorフィルターを使用してください。
  • WP_Widgetのwidget()メソッド内でデータベースクエリを実行する場合は、結果をTransients APIでキャッシュすることを推奨します。サイドバーは全ページで読み込まれるためパフォーマンスに影響します。
  • ウィジェットエリアのbefore_widget/after_widgetHTMLは、テーマのCSSに依存します。テーマを変更するとレイアウトが崩れる可能性があるため、汎用的なクラス名を使用してください。

まとめ

カスタムウィジェット作成は「ウィジェットエリア登録→WP_Widget継承→widget/form/updateメソッド実装→register_widget()で登録→WP-CLIで管理」の流れで実現します。WP-CLIを使えばデプロイ時のウィジェット設定も自動化できます。関連記事:WordPressのサイドバーを最適化する方法WordPressのfunctions.phpを安全に編集する方法

お気軽にご相談ください

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