0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

覚書 WordPressでヘッダーから情報を受け取ってローカルストレージに保存し、条件に応じて表示を制御する実装

Last updated at Posted at 2025-10-22

WordPressでヘッダーから情報を受け取ってローカルストレージに保存し、条件に応じて表示を制御する実装を作成します。​​​​​​​​​​​​​​​​
「headerからsessionと所属コードをwpで受け取ってローカルストレイジに入れたい
値が返って来た時は所属のデータを出す(post type postのカテゴリー)
falseの時は画面出さない」

/**
 * ========================================
 * affiliation-auth.js
 * ========================================
 * テーマフォルダの js/affiliation-auth.js として保存
 * 
 * 機能:
 * - ヘッダーから認証情報を取得
 * - ローカルストレージに保存
 * - 所属カテゴリーの投稿を表示
 * - 認証失敗時は画面を非表示
 */


document.addEventListener('DOMContentLoaded', async function() {
    const contentArea = document.getElementById('affiliation-content');
    
    if (!contentArea) {
        console.log('affiliation-content 要素が見つかりません');
        return;
    }
    
    // ローカルストレージから既存のデータを確認
    const storedData = localStorage.getItem('affiliationData');
    
    if (storedData) {
        try {
            const data = JSON.parse(storedData);
            console.log('ローカルストレージからデータを読み込みました');
            displayContent(data);
            return;
        } catch (e) {
            console.error('ローカルストレージのデータが不正です:', e);
            localStorage.removeItem('affiliationData');
        }
    }
    
    // APIから認証チェック
    await checkAuthentication();
});

/**
 * 認証チェック
 */
async function checkAuthentication() {
    try {
        // セッションと所属コードを取得
        const session = getSessionToken();
        const affiliationCode = getAffiliationCode();
        
        // ヘッダーを準備
        const headers = {
            'Content-Type': 'application/json'
        };
        
        // セッションがある場合はヘッダーに追加
        if (session) {
            // Bearer Tokenかカスタムヘッダーか判定
            if (session.includes('.') && session.split('.').length === 3) {
                // JWT形式の場合はBearer Token
                headers['Authorization'] = 'Bearer ' + session;
            } else {
                // それ以外はカスタムヘッダー
                headers['X-Session'] = session;
            }
        }
        
        // 所属コードがある場合はヘッダーに追加
        if (affiliationCode) {
            headers['X-Affiliation-Code'] = affiliationCode;
        }
        
        console.log('認証チェックを実行中...');
        
        const response = await fetch('/wp-json/custom/v1/auth-check', {
            method: 'GET',
            headers: headers
        });
        
        const data = await response.json();
        
        if (data.success) {
            console.log('認証成功:', data.auth_method);
            
            // ローカルストレージに保存
            localStorage.setItem('affiliationData', JSON.stringify(data));
            localStorage.setItem('session', session);
            localStorage.setItem('affiliationCode', data.affiliation_code);
            
            // コンテンツを表示
            displayContent(data);
        } else {
            console.warn('認証失敗:', data.message);
            console.log('デバッグ情報:', data.debug);
            hideContent();
        }
    } catch (error) {
        console.error('認証エラー:', error);
        hideContent();
    }
}

/**
 * コンテンツを表示
 */
function displayContent(data) {
    const contentArea = document.getElementById('affiliation-content');
    const errorArea = document.getElementById('auth-error');
    
    if (!contentArea) return;
    
    // エラー表示を非表示
    if (errorArea) {
        errorArea.style.display = 'none';
    }
    
    // カテゴリー情報を表示
    let html = `
        <div class="affiliation-header">
            <h2>${escapeHtml(data.category.name)}</h2>
            <p>所属コード: ${escapeHtml(data.affiliation_code)}</p>
        </div>
        <div class="posts-list">
    `;
    
    // 投稿リストを表示
    if (data.posts && data.posts.length > 0) {
        data.posts.forEach(post => {
            html += `
                <article class="post-item">
                    <h3><a href="${escapeHtml(post.link)}">${escapeHtml(post.title)}</a></h3>
                    <time>${formatDate(post.date)}</time>
                    ${post.excerpt ? `<p>${escapeHtml(post.excerpt)}</p>` : ''}
                </article>
            `;
        });
    } else {
        html += '<p>投稿がありません</p>';
    }
    
    html += '</div>';
    
    contentArea.innerHTML = html;
    contentArea.style.display = 'block';
}

/**
 * コンテンツを非表示
 */
function hideContent() {
    const contentArea = document.getElementById('affiliation-content');
    const errorArea = document.getElementById('auth-error');
    
    if (contentArea) {
        contentArea.style.display = 'none';
    }
    
    if (errorArea) {
        errorArea.style.display = 'block';
    }
    
    // 既存のローカルストレージデータをクリア
    localStorage.removeItem('affiliationData');
    localStorage.removeItem('session');
    localStorage.removeItem('affiliationCode');
}

/**
 * セッショントークンを取得する関数
 * 環境に応じてカスタマイズしてください
 */
function getSessionToken() {
    // 方法1: Cookieから取得
    const sessionCookie = document.cookie.split('; ')
        .find(row => row.startsWith('session='))
        ?.split('=')[1];
    
    if (sessionCookie) {
        return sessionCookie;
    }
    
    // 方法2: URLパラメータから取得
    const urlParams = new URLSearchParams(window.location.search);
    const sessionParam = urlParams.get('session');
    
    if (sessionParam) {
        return sessionParam;
    }
    
    // 方法3: ローカルストレージから取得
    const sessionStorage = localStorage.getItem('session');
    
    if (sessionStorage) {
        return sessionStorage;
    }
    
    // 方法4: カスタム実装
    // 例: window.firebaseToken などから取得
    // return window.firebaseToken;
    
    return '';
}

/**
 * 所属コードを取得する関数
 * 環境に応じてカスタマイズしてください
 */
function getAffiliationCode() {
    // 方法1: URLパラメータから取得
    const urlParams = new URLSearchParams(window.location.search);
    const affiliationParam = urlParams.get('affiliation');
    
    if (affiliationParam) {
        return affiliationParam;
    }
    
    // 方法2: Cookieから取得
    const affiliationCookie = document.cookie.split('; ')
        .find(row => row.startsWith('affiliation='))
        ?.split('=')[1];
    
    if (affiliationCookie) {
        return affiliationCookie;
    }
    
    // 方法3: ローカルストレージから取得
    const affiliationStorage = localStorage.getItem('affiliationCode');
    
    if (affiliationStorage) {
        return affiliationStorage;
    }
    
    // 方法4: カスタム実装
    // 例: window.userAffiliation などから取得
    // return window.userAffiliation;
    
    return '';
}

/**
 * ログアウト機能(必要に応じて使用)
 */
function logout() {
    hideContent();
    // 必要に応じてサーバー側のセッションも破棄
    // fetch('/wp-json/custom/v1/logout', { method: 'POST' });
}

/**
 * HTMLエスケープ
 */
function escapeHtml(text) {
    if (!text) return '';
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

/**
 * 日付フォーマット
 */
function formatDate(dateString) {
    const date = new Date(dateString);
    return date.toLocaleDateString('ja-JP', {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    });
}

// グローバルに公開(必要に応じて)
window.affiliationAuth = {
    logout: logout,
    refresh: checkAuthentication
};

<?php
/**
 * ========================================
 * Template Name: Affiliation Content Page
 * ========================================
 * 
 * テーマフォルダに page-affiliation.php として保存
 * または page.php を置き換え
 * 
 * 所属別コンテンツを表示するテンプレート
 */

get_header(); ?>


<main id="main" class="site-main">
    <!-- エラー表示エリア -->
    <div class="auth-error" id="auth-error">
        <h3>🔒 アクセスが制限されています</h3>
        <p>認証に失敗しました。アクセス権限を確認してください。</p>
    </div>

    <!-- コンテンツ表示エリア -->
    <div id="affiliation-content">
        <div class="loading">読み込み中</div>
    </div>
</main>

<?php get_footer(); ?>

<?php
/**
 * ========================================
 * functions.php に追加するコード
 * ========================================
 * 
 * すべてのヘッダー形式に対応した認証システム
 * - Firebase Bearer Token
 * - カスタムヘッダー (X-Session, X-Affiliation-Code)
 * - Basic認証
 * - Cookie
 */

// ========================================
// 1. JavaScriptファイルをエンキュー
// ========================================
function enqueue_affiliation_scripts() {
    wp_enqueue_script(
        'affiliation-auth',
        get_template_directory_uri() . '/js/affiliation-auth.js',
        array(),
        '1.0.0',
        true
    );
}
add_action('wp_enqueue_scripts', 'enqueue_affiliation_scripts');

// ========================================
// 2. ヘッダー情報を柔軟に取得する関数
// ========================================
function get_auth_info_from_request($request) {
    $auth_info = [
        'method' => 'unknown',
        'session' => null,
        'affiliation_code' => null,
        'user_id' => null,
        'raw_data' => []
    ];
    
    // パターン1: Firebase Authentication Bearer Token
    $auth_header = $request->get_header('authorization');
    if ($auth_header && strpos($auth_header, 'Bearer ') === 0) {
        $token = str_replace('Bearer ', '', $auth_header);
        $auth_info['method'] = 'firebase_bearer';
        $auth_info['session'] = $token;
        
        // Firebase ID Tokenを検証・デコード
        $decoded = decode_firebase_token($token);
        if ($decoded) {
            $auth_info['user_id'] = $decoded['user_id'] ?? null;
            $auth_info['affiliation_code'] = $decoded['affiliation'] ?? null;
            $auth_info['raw_data'] = $decoded;
        }
    }
    
    // パターン2: カスタムヘッダー(X-Session, X-Affiliation-Code)
    $session = $request->get_header('X-Session') ?: $request->get_header('x-session');
    $affiliation = $request->get_header('X-Affiliation-Code') ?: $request->get_header('x-affiliation-code');
    
    if ($session || $affiliation) {
        $auth_info['method'] = 'custom_headers';
        $auth_info['session'] = $session;
        $auth_info['affiliation_code'] = $affiliation;
        
        // 追加のカスタムヘッダーもチェック
        $user_id = $request->get_header('X-User-Id') ?: $request->get_header('x-user-id');
        if ($user_id) {
            $auth_info['user_id'] = $user_id;
        }
    }
    
    // パターン3: Cookie
    if (empty($auth_info['session'])) {
        $cookies = $request->get_header('cookie');
        if ($cookies) {
            parse_str(str_replace('; ', '&', $cookies), $cookie_array);
            if (!empty($cookie_array['session'])) {
                $auth_info['method'] = 'cookie';
                $auth_info['session'] = $cookie_array['session'];
                $auth_info['affiliation_code'] = $cookie_array['affiliation'] ?? null;
            }
        }
    }
    
    // すべてのヘッダーをデバッグ用に保存
    $auth_info['all_headers'] = $request->get_headers();
    
    return $auth_info;
}

// ========================================
// 3. Firebase ID Tokenをデコードする関数
// ========================================
function decode_firebase_token($token) {
    // JWT形式かチェック
    $parts = explode('.', $token);
    if (count($parts) !== 3) {
        return null;
    }
    
    try {
        // ペイロード部分をデコード
        $payload = json_decode(base64_decode(str_replace(['-', '_'], ['+', '/'], $parts[1])), true);
        
        // 有効期限チェック
        if (isset($payload['exp']) && $payload['exp'] < time()) {
            return null; // 期限切れ
        }
        
        return $payload;
    } catch (Exception $e) {
        return null;
    }
}

// ========================================
// 4. デバッグ用エンドポイント
// ========================================
add_action('rest_api_init', function () {
    register_rest_route('custom/v1', '/debug-headers', array(
        'methods' => 'GET',
        'callback' => 'debug_all_headers',
        'permission_callback' => '__return_true'
    ));
});

function debug_all_headers($request) {
    $auth_info = get_auth_info_from_request($request);
    
    return new WP_REST_Response([
        'detected_method' => $auth_info['method'],
        'extracted_info' => [
            'session' => $auth_info['session'] ? 'present (hidden for security)' : 'missing',
            'affiliation_code' => $auth_info['affiliation_code'] ?: 'missing',
            'user_id' => $auth_info['user_id'] ?: 'missing'
        ],
        'all_headers' => $auth_info['all_headers'],
        'raw_token_data' => $auth_info['raw_data'],
        'tips' => [
            'detected' => $auth_info['method'],
            'message' => get_method_message($auth_info['method'])
        ]
    ], 200);
}

function get_method_message($method) {
    $messages = [
        'firebase_bearer' => '✅ Firebase Bearer Tokenを検出しました',
        'custom_headers' => '✅ カスタムヘッダー (X-Session, X-Affiliation-Code) を検出しました',
        'cookie' => '✅ Cookie認証を検出しました',
        'unknown' => '❌ 認証情報が見つかりません。all_headersを確認してください'
    ];
    
    return $messages[$method] ?? $messages['unknown'];
}

// ========================================
// 5. 実際の認証エンドポイント
// ========================================
add_action('rest_api_init', function () {
    register_rest_route('custom/v1', '/auth-check', array(
        'methods' => 'GET',
        'callback' => 'handle_flexible_auth_check',
        'permission_callback' => '__return_true'
    ));
});

function handle_flexible_auth_check($request) {
    // 柔軟に認証情報を取得
    $auth_info = get_auth_info_from_request($request);
    
    // ログに記録
    error_log('Auth Check - Method: ' . $auth_info['method']);
    error_log('Auth Check - Session: ' . ($auth_info['session'] ? 'present' : 'missing'));
    error_log('Auth Check - Affiliation: ' . ($auth_info['affiliation_code'] ?? 'missing'));
    
    // 認証情報がない場合
    if (empty($auth_info['session'])) {
        return new WP_REST_Response([
            'success' => false,
            'message' => '認証情報が見つかりません',
            'debug' => [
                'detected_method' => $auth_info['method'],
                'help' => '/wp-json/custom/v1/debug-headers にアクセスして詳細を確認してください'
            ]
        ], 401);
    }
    
    // 所属コードがない場合の処理
    if (empty($auth_info['affiliation_code'])) {
        // オプション1: デフォルト所属を設定(必要に応じてコメント解除)
        // $auth_info['affiliation_code'] = 'default';
        
        // オプション2: エラーを返す(現在の実装)
        return new WP_REST_Response([
            'success' => false,
            'message' => '所属コードが見つかりません',
            'debug' => [
                'detected_method' => $auth_info['method'],
                'session' => 'present',
                'affiliation_code' => 'missing',
                'user_id' => $auth_info['user_id'] ?? 'none',
                'raw_token_data' => $auth_info['raw_data'],
                'help' => [
                    'Firebase Custom Claimsに affiliation フィールドを追加してください',
                    'または X-Affiliation-Code ヘッダーを追加で送信してください',
                    'トークンのデコード結果は raw_token_data を確認してください'
                ]
            ]
        ], 400);
    }
    
    // カテゴリーを取得
    $category = get_category_by_slug($auth_info['affiliation_code']);
    
    if (!$category) {
        return new WP_REST_Response([
            'success' => false,
            'message' => '該当する所属カテゴリーが見つかりません',
            'debug' => [
                'affiliation_code' => $auth_info['affiliation_code'],
                'available_categories' => array_map(function($cat) {
                    return ['slug' => $cat->slug, 'name' => $cat->name];
                }, get_categories(['hide_empty' => false]))
            ]
        ], 404);
    }
    
    // 投稿を取得
    $posts = get_posts(array(
        'category' => $category->term_id,
        'post_type' => 'post',
        'posts_per_page' => 10,
        'orderby' => 'date',
        'order' => 'DESC'
    ));
    
    $posts_data = array_map(function($post) {
        return [
            'id' => $post->ID,
            'title' => $post->post_title,
            'excerpt' => $post->post_excerpt,
            'date' => $post->post_date,
            'link' => get_permalink($post->ID)
        ];
    }, $posts);
    
    return new WP_REST_Response([
        'success' => true,
        'auth_method' => $auth_info['method'],
        'session' => substr($auth_info['session'], 0, 20) . '...', // セキュリティのため一部のみ
        'affiliation_code' => $auth_info['affiliation_code'],
        'user_id' => $auth_info['user_id'],
        'category' => [
            'id' => $category->term_id,
            'name' => $category->name,
            'slug' => $category->slug
        ],
        'posts' => $posts_data
    ], 200);
}

// ========================================
// 6. CORS設定(必要な場合)
// ========================================
add_action('rest_api_init', function() {
    remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
    add_filter('rest_pre_serve_request', function($value) {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
        header('Access-Control-Allow-Headers: Authorization, X-Session, X-Affiliation-Code, X-User-Id, Content-Type');
        header('Access-Control-Allow-Credentials: true');
        return $value;
    });
}, 15);

📦 4つのファイルで完結

1️⃣ functions.php に追加

「WordPress完全実装ガイド」をコピー&ペースト

2️⃣ js/affiliation-auth.js を作成

「affiliation-auth.js(完全版)」の内容で新規ファイル作成

3️⃣ page-affiliation.php を作成

「page-affiliation.php(完全版テンプレート)」の内容で新規ファイル作成

4️⃣ セットアップガイドを参照

「WordPress実装ガイド(完全版)」を見ながら設定

✨ 実装済みの機能

✅ Firebase Bearer Token 対応
✅ カスタムヘッダー (X-Session, X-Affiliation-Code) 対応
✅ 自動判別機能
✅ ローカルストレージ保存
✅ デバッグエンドポイント
✅ エラーハンドリング
✅ CORS対応
✅ セキュリティ対策
✅ レスポンシブデザイン

WordPress実装ガイド(完全版)

📦 ファイル構成

your-theme/
├── functions.php              ← アーティファクト1のコードを追加
├── js/
│   └── affiliation-auth.js   ← アーティファクト2のコードを保存
└── page-affiliation.php       ← アーティファクト3のコードを保存
    (または page.php)

🚀 セットアップ手順

ステップ1: functions.php に追加

  1. WordPress管理画面 > 外観 > テーマエディター
  2. functions.php を開く
  3. **アーティファクト1「WordPress完全実装ガイド」**の全コードをコピー
  4. functions.php の最後に貼り付け
  5. 「ファイルを更新」をクリック

ステップ2: JavaScriptファイルを作成

  1. FTPまたはファイルマネージャーでテーマフォルダにアクセス
  2. js フォルダを作成(存在しない場合)
  3. js/affiliation-auth.js ファイルを作成
  4. **アーティファクト2「affiliation-auth.js」**の全コードをコピー
  5. ファイルに貼り付けて保存

または、管理画面から:

  • プラグイン「Simple Custom CSS and JS」をインストール
  • カスタムJSとして追加

ステップ3: テンプレートファイルを作成

  1. FTPまたはファイルマネージャーでテーマフォルダにアクセス
  2. page-affiliation.php ファイルを作成
  3. **アーティファクト3「page-affiliation.php」**の全コードをコピー
  4. ファイルに貼り付けて保存

既存のpage.phpを使う場合:

  • page.php を開いて内容を置き換える

ステップ4: 固定ページを作成

  1. WordPress管理画面 > 固定ページ > 新規追加
  2. タイトル: 「所属コンテンツ」など任意
  3. 右サイドバー「ページ属性」>「テンプレート」から「Affiliation Content Page」を選択
  4. 公開

ステップ5: カテゴリーを作成

  1. WordPress管理画面 > 投稿 > カテゴリー
  2. テスト用カテゴリーを作成
    • 名前: 「営業部」
    • スラッグ: sales ← これが重要!
  3. 他にも必要な所属カテゴリーを作成
    • 例: 「開発部」 (slug: development)
    • 例: 「総務部」 (slug: general-affairs)

ステップ6: テスト投稿を作成

  1. WordPress管理画面 > 投稿 > 新規追加
  2. タイトルと本文を入力
  3. カテゴリーから「営業部」を選択
  4. 公開

✅ 動作確認

1. デバッグエンドポイントで確認

ブラウザで以下のURLにアクセス:

https://your-site.com/wp-json/custom/v1/debug-headers

期待される結果:

{
  "detected_method": "unknown",
  "extracted_info": {
    "session": "missing",
    "affiliation_code": "missing",
    "user_id": "missing"
  },
  "all_headers": {...},
  "tips": {
    "detected": "unknown",
    "message": "❌ 認証情報が見つかりません"
  }
}

2. ヘッダー付きでテスト

方法A: ブラウザの開発者ツール (F12)

// Consoleタブで実行
fetch('/wp-json/custom/v1/auth-check', {
    headers: {
        'X-Session': 'test-session-123',
        'X-Affiliation-Code': 'sales'
    }
})
.then(r => r.json())
.then(console.log);

方法B: cURLコマンド

curl -H "X-Session: test-123" \
     -H "X-Affiliation-Code: sales" \
     https://your-site.com/wp-json/custom/v1/auth-check

3. テストページで確認

前回作成した「テスト用HTMLページ」を使用:

  1. ブラウザで開く
  2. セッションと所属コードを入力
  3. テスト実行

🔧 カスタマイズ

セッションの取得方法を変更

js/affiliation-auth.jsgetSessionToken() 関数を編集:

function getSessionToken() {
    // あなたのシステムに合わせて変更
    return window.yourSessionVariable; // 例
}

所属コードの取得方法を変更

js/affiliation-auth.jsgetAffiliationCode() 関数を編集:

function getAffiliationCode() {
    // あなたのシステムに合わせて変更
    return window.userDepartment; // 例
}

デフォルト所属を設定

認証情報が無い場合にデフォルトの所属を表示したい場合、
functions.php の以下の部分をコメント解除:

// 所属コードがない場合の処理(73行目あたり)
if (empty($auth_info['affiliation_code'])) {
    // この行のコメントを外す
    $auth_info['affiliation_code'] = 'default';  // ← ここ
    
    // エラーを返す行をコメントアウト
    // return new WP_REST_Response([...
}

🧪 Flutter/Firebaseとの連携テスト

Flutter側でテストリクエストを送る

import 'package:http/http.dart' as http;

// テスト1: カスタムヘッダー
final response1 = await http.get(
  Uri.parse('https://your-wp-site.com/wp-json/custom/v1/debug-headers'),
  headers: {
    'X-Session': 'test-session-123',
    'X-Affiliation-Code': 'sales',
  },
);
print('Response: ${response1.body}');

// テスト2: Bearer Token
final token = await FirebaseAuth.instance.currentUser?.getIdToken();
final response2 = await http.get(
  Uri.parse('https://your-wp-site.com/wp-json/custom/v1/debug-headers'),
  headers: {
    'Authorization': 'Bearer $token',
  },
);
print('Response: ${response2.body}');

期待される結果

{
  "detected_method": "custom_headers",  // または "firebase_bearer"
  "extracted_info": {
    "session": "present (hidden for security)",
    "affiliation_code": "sales",
    "user_id": "missing"
  },
  "tips": {
    "message": "✅ カスタムヘッダーを検出しました"
  }
}

🐛 トラブルシューティング

エラー: 404 Not Found (REST APIが見つからない)

原因: パーマリンク設定の問題

解決方法:

  1. WordPress管理画面 > 設定 > パーマリンク
  2. 「変更を保存」をクリック(設定を変更しなくてもOK)
  3. これでREST APIが認識されます

エラー: affiliation-auth.js が読み込まれない

確認項目:

  1. ファイルパスが正しいか確認
    https://your-site.com/wp-content/themes/your-theme/js/affiliation-auth.js
    
  2. functions.php の enqueue が正しいか確認
  3. ブラウザの開発者ツール(F12)> Networkタブで確認

解決方法:

// functions.php で直接パスを指定
function enqueue_affiliation_scripts() {
    wp_enqueue_script(
        'affiliation-auth',
        get_stylesheet_directory_uri() . '/js/affiliation-auth.js', // ← 変更
        array(),
        '1.0.1', // バージョンを変更してキャッシュクリア
        true
    );
}

エラー: CORS エラー

症状: ブラウザのコンソールに「CORS policy」エラー

解決方法: 既に functions.php にCORS設定が含まれています。
それでもエラーが出る場合:

// functions.php に追加
add_action('init', function() {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Authorization, X-Session, X-Affiliation-Code');
});

問題: ヘッダーが受信されない

確認方法:

/wp-json/custom/v1/debug-headers

all_headers を確認

Apache の場合:
.htaccess に追加:

<IfModule mod_headers.c>
    SetEnvIf X-Session "(.+)" HTTP_X_SESSION=$1
    SetEnvIf X-Affiliation-Code "(.+)" HTTP_X_AFFILIATION_CODE=$1
</IfModule>

Nginx の場合:
nginx.conf に追加:

location ~ ^/wp-json/ {
    fastcgi_param HTTP_X_SESSION $http_x_session;
    fastcgi_param HTTP_X_AFFILIATION_CODE $http_x_affiliation_code;
}

問題: ローカルストレージに保存されない

確認方法:

  1. ブラウザの開発者ツール(F12)
  2. Application(またはStorage)タブ
  3. Local Storage を確認

解決方法:

  • プライベートブラウジングを使用していないか確認
  • サイトのCookieがブロックされていないか確認

📊 動作フロー

1. ユーザーがページにアクセス
   ↓
2. affiliation-auth.js が実行
   ↓
3. ローカルストレージをチェック
   ├─ データがある → 表示
   └─ データがない → APIリクエスト
       ↓
4. /wp-json/custom/v1/auth-check にリクエスト
   ├─ ヘッダーに認証情報を含める
   └─ WordPress側で認証情報を取得
       ↓
5. 認証情報を確認
   ├─ OK → カテゴリーの投稿を取得
   │        ↓
   │    レスポンスを返す
   │        ↓
   │    ローカルストレージに保存
   │        ↓
   │    画面に表示
   │
   └─ NG → エラーレスポンス
            ↓
        エラー画面を表示

🎯 チェックリスト

実装が完了したら以下を確認:

  • functions.php にコードを追加した
  • js/affiliation-auth.js を作成した
  • page-affiliation.php を作成した
  • カテゴリーを作成した(slugを確認)
  • テスト投稿を作成した
  • 固定ページを作成した
  • /wp-json/custom/v1/debug-headers にアクセスできる
  • ブラウザの開発者ツールでエラーがない
  • Flutter/Firebase側からテストリクエストを送信
  • 正しいレスポンスが返ってくる
  • ローカルストレージに保存される
  • 画面にコンテンツが表示される

サポート

問題が解決しない場合:

  1. ブラウザの開発者ツール(F12)のConsoleタブを確認
  2. /wp-json/custom/v1/debug-headers のレスポンスを確認
  3. WordPress の wp-content/debug.log を確認

必要な情報:

  • エラーメッセージ
  • デバッグエンドポイントのレスポンス
  • ブラウザのコンソールログ

WordPress実装ガイド(完全版)

📦 ファイル構成

your-theme/
├── functions.php              ← アーティファクト1のコードを追加
├── js/
│   └── affiliation-auth.js   ← アーティファクト2のコードを保存
└── page-affiliation.php       ← アーティファクト3のコードを保存
    (または page.php)

🚀 セットアップ手順

ステップ1: functions.php に追加

  1. WordPress管理画面 > 外観 > テーマエディター
  2. functions.php を開く
  3. **アーティファクト1「WordPress完全実装ガイド」**の全コードをコピー
  4. functions.php の最後に貼り付け
  5. 「ファイルを更新」をクリック

ステップ2: JavaScriptファイルを作成

  1. FTPまたはファイルマネージャーでテーマフォルダにアクセス
  2. js フォルダを作成(存在しない場合)
  3. js/affiliation-auth.js ファイルを作成
  4. **アーティファクト2「affiliation-auth.js」**の全コードをコピー
  5. ファイルに貼り付けて保存

または、管理画面から:

  • プラグイン「Simple Custom CSS and JS」をインストール
  • カスタムJSとして追加

ステップ3: テンプレートファイルを作成

  1. FTPまたはファイルマネージャーでテーマフォルダにアクセス
  2. page-affiliation.php ファイルを作成
  3. **アーティファクト3「page-affiliation.php」**の全コードをコピー
  4. ファイルに貼り付けて保存

既存のpage.phpを使う場合:

  • page.php を開いて内容を置き換える

ステップ4: 固定ページを作成

  1. WordPress管理画面 > 固定ページ > 新規追加
  2. タイトル: 「所属コンテンツ」など任意
  3. 右サイドバー「ページ属性」>「テンプレート」から「Affiliation Content Page」を選択
  4. 公開

ステップ5: カテゴリーを作成

  1. WordPress管理画面 > 投稿 > カテゴリー
  2. テスト用カテゴリーを作成
    • 名前: 「営業部」
    • スラッグ: sales ← これが重要!
  3. 他にも必要な所属カテゴリーを作成
    • 例: 「開発部」 (slug: development)
    • 例: 「総務部」 (slug: general-affairs)

ステップ6: テスト投稿を作成

  1. WordPress管理画面 > 投稿 > 新規追加
  2. タイトルと本文を入力
  3. カテゴリーから「営業部」を選択
  4. 公開

✅ 動作確認

1. デバッグエンドポイントで確認

ブラウザで以下のURLにアクセス:

https://your-site.com/wp-json/custom/v1/debug-headers

期待される結果:

{
  "detected_method": "unknown",
  "extracted_info": {
    "session": "missing",
    "affiliation_code": "missing",
    "user_id": "missing"
  },
  "all_headers": {...},
  "tips": {
    "detected": "unknown",
    "message": "❌ 認証情報が見つかりません"
  }
}

2. ヘッダー付きでテスト

方法A: ブラウザの開発者ツール (F12)

// Consoleタブで実行
fetch('/wp-json/custom/v1/auth-check', {
    headers: {
        'X-Session': 'test-session-123',
        'X-Affiliation-Code': 'sales'
    }
})
.then(r => r.json())
.then(console.log);

方法B: cURLコマンド

curl -H "X-Session: test-123" \
     -H "X-Affiliation-Code: sales" \
     https://your-site.com/wp-json/custom/v1/auth-check

3. テストページで確認

前回作成した「テスト用HTMLページ」を使用:

  1. ブラウザで開く
  2. セッションと所属コードを入力
  3. テスト実行

🔧 カスタマイズ

セッションの取得方法を変更

js/affiliation-auth.jsgetSessionToken() 関数を編集:

function getSessionToken() {
    // あなたのシステムに合わせて変更
    return window.yourSessionVariable; // 例
}

所属コードの取得方法を変更

js/affiliation-auth.jsgetAffiliationCode() 関数を編集:

function getAffiliationCode() {
    // あなたのシステムに合わせて変更
    return window.userDepartment; // 例
}

デフォルト所属を設定

認証情報が無い場合にデフォルトの所属を表示したい場合、
functions.php の以下の部分をコメント解除:

// 所属コードがない場合の処理(73行目あたり)
if (empty($auth_info['affiliation_code'])) {
    // この行のコメントを外す
    $auth_info['affiliation_code'] = 'default';  // ← ここ
    
    // エラーを返す行をコメントアウト
    // return new WP_REST_Response([...
}

🧪 Flutter/Firebaseとの連携テスト

Flutter側でテストリクエストを送る

import 'package:http/http.dart' as http;

// テスト1: カスタムヘッダー
final response1 = await http.get(
  Uri.parse('https://your-wp-site.com/wp-json/custom/v1/debug-headers'),
  headers: {
    'X-Session': 'test-session-123',
    'X-Affiliation-Code': 'sales',
  },
);
print('Response: ${response1.body}');

// テスト2: Bearer Token
final token = await FirebaseAuth.instance.currentUser?.getIdToken();
final response2 = await http.get(
  Uri.parse('https://your-wp-site.com/wp-json/custom/v1/debug-headers'),
  headers: {
    'Authorization': 'Bearer $token',
  },
);
print('Response: ${response2.body}');

期待される結果

{
  "detected_method": "custom_headers",  // または "firebase_bearer"
  "extracted_info": {
    "session": "present (hidden for security)",
    "affiliation_code": "sales",
    "user_id": "missing"
  },
  "tips": {
    "message": "✅ カスタムヘッダーを検出しました"
  }
}

🐛 トラブルシューティング

エラー: 404 Not Found (REST APIが見つからない)

原因: パーマリンク設定の問題

解決方法:

  1. WordPress管理画面 > 設定 > パーマリンク
  2. 「変更を保存」をクリック(設定を変更しなくてもOK)
  3. これでREST APIが認識されます

エラー: affiliation-auth.js が読み込まれない

確認項目:

  1. ファイルパスが正しいか確認
    https://your-site.com/wp-content/themes/your-theme/js/affiliation-auth.js
    
  2. functions.php の enqueue が正しいか確認
  3. ブラウザの開発者ツール(F12)> Networkタブで確認

解決方法:

// functions.php で直接パスを指定
function enqueue_affiliation_scripts() {
    wp_enqueue_script(
        'affiliation-auth',
        get_stylesheet_directory_uri() . '/js/affiliation-auth.js', // ← 変更
        array(),
        '1.0.1', // バージョンを変更してキャッシュクリア
        true
    );
}

エラー: CORS エラー

症状: ブラウザのコンソールに「CORS policy」エラー

解決方法: 既に functions.php にCORS設定が含まれています。
それでもエラーが出る場合:

// functions.php に追加
add_action('init', function() {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
    header('Access-Control-Allow-Headers: Authorization, X-Session, X-Affiliation-Code');
});

問題: ヘッダーが受信されない

確認方法:

/wp-json/custom/v1/debug-headers

all_headers を確認

Apache の場合:
.htaccess に追加:

<IfModule mod_headers.c>
    SetEnvIf X-Session "(.+)" HTTP_X_SESSION=$1
    SetEnvIf X-Affiliation-Code "(.+)" HTTP_X_AFFILIATION_CODE=$1
</IfModule>

Nginx の場合:
nginx.conf に追加:

location ~ ^/wp-json/ {
    fastcgi_param HTTP_X_SESSION $http_x_session;
    fastcgi_param HTTP_X_AFFILIATION_CODE $http_x_affiliation_code;
}

問題: ローカルストレージに保存されない

確認方法:

  1. ブラウザの開発者ツール(F12)
  2. Application(またはStorage)タブ
  3. Local Storage を確認

解決方法:

  • プライベートブラウジングを使用していないか確認
  • サイトのCookieがブロックされていないか確認

📊 動作フロー

1. ユーザーがページにアクセス
   ↓
2. affiliation-auth.js が実行
   ↓
3. ローカルストレージをチェック
   ├─ データがある → 表示
   └─ データがない → APIリクエスト
       ↓
4. /wp-json/custom/v1/auth-check にリクエスト
   ├─ ヘッダーに認証情報を含める
   └─ WordPress側で認証情報を取得
       ↓
5. 認証情報を確認
   ├─ OK → カテゴリーの投稿を取得
   │        ↓
   │    レスポンスを返す
   │        ↓
   │    ローカルストレージに保存
   │        ↓
   │    画面に表示
   │
   └─ NG → エラーレスポンス
            ↓
        エラー画面を表示

🎯 チェックリスト

実装が完了したら以下を確認:

  • functions.php にコードを追加した
  • js/affiliation-auth.js を作成した
  • page-affiliation.php を作成した
  • カテゴリーを作成した(slugを確認)
  • テスト投稿を作成した
  • 固定ページを作成した
  • /wp-json/custom/v1/debug-headers にアクセスできる
  • ブラウザの開発者ツールでエラーがない
  • Flutter/Firebase側からテストリクエストを送信
  • 正しいレスポンスが返ってくる
  • ローカルストレージに保存される
  • 画面にコンテンツが表示される

📞 サポート

問題が解決しない場合:

  1. ブラウザの開発者ツール(F12)のConsoleタブを確認
  2. /wp-json/custom/v1/debug-headers のレスポンスを確認
  3. WordPress の wp-content/debug.log を確認

必要な情報:

  • エラーメッセージ
  • デバッグエンドポイントのレスポンス
  • ブラウザのコンソールログ
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?