2026年6月26日

2026年6月26日

WordPressでメンバーシップサイトを構築する方法【会員限定コンテンツ実装】

はじめに

メンバーシップサイトでは登録ユーザーのみが閲覧できる限定コンテンツを提供します。WordPressはユーザー管理機能を標準搭載しているため、カスタムコードで完全なメンバーシップ機能を実装できます。

症状・原因

  • 有料会員のみアクセスできるコンテンツページが必要
  • 無料会員と有料会員でコンテンツの表示範囲を変えたい
  • ログインしていないユーザーにはコンテンツを見せずに登録ページに誘導したい

解決手順

ステップ1:会員ランクシステムを実装する

// functions.php: 会員ランク管理クラス
class Membership_Manager {

    // 会員ランク定義
    const RANKS = [
        'free'    => ['label' => '無料会員', 'priority' => 1],
        'basic'   => ['label' => 'ベーシック会員', 'priority' => 2],
        'premium' => ['label' => 'プレミアム会員', 'priority' => 3],
    ];

    // ユーザーの会員ランクを取得
    public static function get_rank(int $user_id = 0): string {
        if (!$user_id) $user_id = get_current_user_id();

        $rank = get_user_meta($user_id, '_membership_rank', true);

        return in_array($rank, array_keys(self::RANKS), true) ? $rank : 'free';
    }

    // 会員ランクを設定
    public static function set_rank(int $user_id, string $rank): bool {
        if (!isset(self::RANKS[$rank])) return false;

        update_user_meta($user_id, '_membership_rank', $rank);

        // ランクに対応するロールも設定
        $user = get_user_by('id', $user_id);
        if ($user) {
            $user->set_role($rank === 'free' ? 'subscriber' : 'subscriber');
            // ランク専用capabilityを付与
            $user->add_cap("membership_{$rank}");
        }

        return true;
    }

    // 指定ランク以上かチェック
    public static function has_rank(string $required_rank, int $user_id = 0): bool {
        if (!is_user_logged_in()) return false;

        $current_rank = self::get_rank($user_id ?: get_current_user_id());

        $current_priority  = self::RANKS[$current_rank]['priority']  ?? 0;
        $required_priority = self::RANKS[$required_rank]['priority'] ?? 999;

        return $current_priority >= $required_priority;
    }
}

ステップ2:コンテンツ制限機能を実装する

// ショートコードで会員限定コンテンツを表示
add_shortcode('members_only', function(array $atts, ?string $content = null): string {
    $atts = shortcode_atts([
        'rank'     => 'basic',   // 必要なランク
        'login_msg'=> 'ログインしてください。',
        'rank_msg' => 'この会員プランではご利用いただけません。',
    ], $atts, 'members_only');

    // 未ログイン
    if (!is_user_logged_in()) {
        $login_url = wp_login_url(get_permalink());
        return sprintf(
            '<div class="membership-gate">
                <p>%s</p>
                <a href="%s" class="button">ログイン</a>
                <a href="%s" class="button">新規登録</a>
            </div>',
            esc_html($atts['login_msg']),
            esc_url($login_url),
            esc_url(wp_registration_url())
        );
    }

    // ランク不足
    if (!Membership_Manager::has_rank($atts['rank'])) {
        return sprintf(
            '<div class="membership-upgrade">
                <p>%s</p>
                <a href="%s" class="button">アップグレード</a>
            </div>',
            esc_html($atts['rank_msg']),
            esc_url(home_url('/membership-plans/'))
        );
    }

    // コンテンツを表示
    return '<div class="members-content">' . do_shortcode($content) . '</div>';
});

// 投稿全体を会員限定にするカスタムフィールド
add_filter('the_content', function(string $content): string {
    if (!is_singular()) return $content;

    $post_id       = get_the_ID();
    $required_rank = get_post_meta($post_id, '_required_membership_rank', true);

    if (!$required_rank || $required_rank === 'none') return $content;

    // ログインチェック
    if (!is_user_logged_in()) {
        $excerpt = wp_trim_words($content, 50, '...');
        return $excerpt . sprintf(
            '<div class="membership-gate">
                <p>この記事の続きを読むには<a href="%s">ログイン</a>または<a href="%s">会員登録</a>が必要です。</p>
            </div>',
            esc_url(wp_login_url(get_permalink())),
            esc_url(wp_registration_url())
        );
    }

    // ランクチェック
    if (!Membership_Manager::has_rank($required_rank)) {
        $excerpt = wp_trim_words($content, 50, '...');
        return $excerpt . '<div class="membership-upgrade"><p>続きを読むには上位プランへのアップグレードが必要です。</p></div>';
    }

    return $content;
});

ステップ3:会員登録フォームをカスタマイズする

// カスタム登録フォームを追加
add_shortcode('custom_registration', function(): string {
    if (is_user_logged_in()) {
        return '<p>すでにログインしています。<a href="' . esc_url(admin_url()) . '">ダッシュボードへ</a></p>';
    }

    // 登録処理
    $errors = [];
    if ('POST' === $_SERVER['REQUEST_METHOD'] && isset($_POST['register_user'])) {
        check_admin_referer('custom_register_user', 'registration_nonce');

        $username = sanitize_user($_POST['user_login'] ?? '');
        $email    = sanitize_email($_POST['user_email'] ?? '');
        $password = $_POST['user_pass'] ?? '';

        if (empty($username) || empty($email) || empty($password)) {
            $errors[] = 'すべての項目を入力してください。';
        } elseif (username_exists($username)) {
            $errors[] = 'このユーザー名はすでに使用されています。';
        } elseif (email_exists($email)) {
            $errors[] = 'このメールアドレスはすでに登録されています。';
        } else {
            $user_id = wp_create_user($username, $password, $email);

            if (!is_wp_error($user_id)) {
                // デフォルトで無料会員に設定
                Membership_Manager::set_rank($user_id, 'free');

                wp_set_current_user($user_id);
                wp_set_auth_cookie($user_id);
                wp_redirect(home_url('/members/'));
                exit;
            }
        }
    }

    ob_start();
    if ($errors) {
        foreach ($errors as $error) {
            echo '<div class="notice error"><p>' . esc_html($error) . '</p></div>';
        }
    }
    ?>
    <form method="post">
        <?php wp_nonce_field('custom_register_user', 'registration_nonce'); ?>
        <p><label>ユーザー名: <input type="text" name="user_login" required></label></p>
        <p><label>メールアドレス: <input type="email" name="user_email" required></label></p>
        <p><label>パスワード: <input type="password" name="user_pass" required minlength="8"></label></p>
        <p><button type="submit" name="register_user">登録する</button></p>
    </form>
    <?php
    return ob_get_clean();
});

ステップ4:会員ページを保護する

// 指定ページへの未ログインアクセスをリダイレクト
add_action('template_redirect', function(): void {
    if (is_user_logged_in()) return;

    // 会員限定ページのスラッグリスト
    $protected_slugs = ['members', 'my-account', 'premium-content'];

    global $post;
    if (!$post) return;

    if (in_array($post->post_name, $protected_slugs, true)) {
        wp_redirect(wp_login_url(get_permalink()), 302);
        exit;
    }
});

// 投稿タイプ別の閲覧制限
add_action('template_redirect', function(): void {
    if (!is_singular('premium_post')) return;

    if (!is_user_logged_in()) {
        wp_redirect(wp_login_url(get_permalink()), 302);
        exit;
    }

    if (!Membership_Manager::has_rank('premium')) {
        wp_redirect(home_url('/upgrade/'), 302);
        exit;
    }
});

ステップ5:会員ダッシュボードを作成する

// 会員マイページのショートコード
add_shortcode('member_dashboard', function(): string {
    if (!is_user_logged_in()) {
        return '<p>ログインしてください。</p>';
    }

    $user_id   = get_current_user_id();
    $user      = get_userdata($user_id);
    $rank      = Membership_Manager::get_rank($user_id);
    $rank_label = Membership_Manager::RANKS[$rank]['label'] ?? '無料会員';

    ob_start();
    ?>
    <div class="member-dashboard">
        <h2>ようこそ、<?php echo esc_html($user->display_name); ?>さん</h2>
        <p>現在のプラン: <strong><?php echo esc_html($rank_label); ?></strong></p>

        <ul class="member-links">
            <li><a href="<?php echo esc_url(home_url('/members/')); ?>">会員コンテンツ一覧</a></li>
            <li><a href="<?php echo esc_url(home_url('/profile/')); ?>">プロフィール編集</a></li>
            <li><a href="<?php echo esc_url(wp_logout_url(home_url('/'))); ?>">ログアウト</a></li>
        </ul>
    </div>
    <?php
    return ob_get_clean();
});

注意事項

  • 決済連携: 有料メンバーシップには決済システム(Stripe・PayPal・WooCommerce Memberships)との連携が必要です。本記事のコードは決済機能を含みません
  • セキュリティ: the_contentフィルターでのコンテンツ制限はREST API経由では機能しません。REST APIでのアクセスも制限する場合はrest_prepare_postフィルターを使用してください
  • キャッシュ: ページキャッシュとの相性に注意してください。ログインユーザーにはキャッシュを提供しない設定が必要です

まとめ

メンバーシップサイトの構築は「会員ランク定義→コンテンツ制限ショートコード→登録フォーム→保護ページ設定→会員ダッシュボード」の5ステップです。プラグインを使わずWordPressのUser Meta・Capabilities・フックを活用することで高度なカスタマイズが可能です。関連記事:ユーザー権限のカスタマイズ方法

お気軽にご相談ください

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