【WordPress】Ajax+非公開カスタム投稿で問い合わせ履歴をユーザーにだけ表示する方法

【WordPress】Ajax+非公開カスタム投稿で問い合わせ履歴をユーザーにだけ表示する方法 WordPress

会員制サイトやカスタマーサポート機能をWordPressで実装する際、ユーザーごとの問い合わせ履歴を表示したい場面があります。この記事では、「非公開のカスタム投稿タイプ」を活用して、ログインユーザー自身だけが自分の履歴を閲覧できる仕組みを、Ajaxで非同期表示する方法とともに解説します。

スポンサーリンク

カスタム投稿タイプ「inquiry」を作成する

まずは、問い合わせ履歴を保存するためのカスタム投稿タイプinquiryを登録します。

functions.php:カスタム投稿タイプの登録
function register_inquiry_post_type() {
  register_post_type('inquiry', array(
    'label' => '問い合わせ履歴',
    'public' => false,
    'show_ui' => true,
    'supports' => array('title', 'editor', 'author'),
    'capability_type' => 'post',
  ));
}
add_action('init', 'register_inquiry_post_type');

‘public’ => false にすることで、検索や一覧には表示されず、非公開の履歴管理が可能になります。

問い合わせを作成する処理(前提)

以降のAjax表示は、post_status=’private’・正しいpost_authorで問い合わせ投稿が既に作成されていることが前提です。問い合わせフォームの送信処理では、以下のように投稿を作成します。

functions.php:問い合わせ投稿の作成例
// 問い合わせフォーム送信時の投稿作成例
function create_inquiry_post($title, $content) {
  if (!is_user_logged_in()) {
    return false;
  }

  return wp_insert_post(array(
    'post_type'   => 'inquiry',
    'post_title'  => sanitize_text_field($title),
    'post_content'=> sanitize_textarea_field($content),
    'post_status' => 'private', // 必ずprivateにする
    'post_author' => get_current_user_id(), // 送信者本人を投稿者にする
  ));
}

Ajax用のJavaScriptを用意する

次に、ログインユーザーが自分の問い合わせ履歴を非同期で取得するためのJavaScriptを記述します。まず、スクリプトを正しく読み込み、Ajax URLとnonceをJavaScript側に渡します。

functions.php:スクリプトの読み込みとnonceの受け渡し
function enqueue_user_inquiries_script() {
  wp_enqueue_script('user-inquiries', get_stylesheet_directory_uri() . '/js/user-inquiries.js', array('jquery'), null, true);
  wp_localize_script('user-inquiries', 'ajax_object', array(
    'ajax_url' => admin_url('admin-ajax.php'),
    'nonce'    => wp_create_nonce('user_inquiries_nonce'),
  ));
}
add_action('wp_enqueue_scripts', 'enqueue_user_inquiries_script');

ajax_object.ajax_urlはこのwp_localize_script()によって初めて定義されます。これがないとJavaScript側でエラーになりAjaxリクエストが送信されないため、必ずセットで実装してください。

js/user-inquiries.js
jQuery(document).ready(function($) {
  $.ajax({
    url: ajax_object.ajax_url,
    type: 'POST',
    data: {
      action: 'load_user_inquiries',
      nonce: ajax_object.nonce
    },
    success: function(response) {
      if (response.success) {
        $('#user-inquiry-list').html(response.data);
      }
    }
  });
});

このコードでは、Ajax経由でload_user_inquiriesというアクションを呼び出し、取得結果を#user-inquiry-listに出力します。

Ajax処理で問い合わせ履歴を取得する

Ajaxに応答するPHP関数をfunctions.phpに記述します。nonceを検証したうえで、ログインユーザーに限定して自分の投稿だけを取得します。

functions.php:Ajaxハンドラー
function ajax_load_user_inquiries() {
  check_ajax_referer('user_inquiries_nonce', 'nonce');

  if (!is_user_logged_in()) {
    wp_send_json_error('ログインが必要です');
  }

  $current_user_id = get_current_user_id();

  $args = array(
    'post_type' => 'inquiry',
    'post_status' => 'private',
    'author' => $current_user_id,
    'posts_per_page' => -1
  );
  $query = new WP_Query($args);

  if ($query->have_posts()) {
    ob_start();
    echo '<ul>';
    while ($query->have_posts()) {
      $query->the_post();
      echo '<li><strong>' . esc_html(get_the_title()) . '</strong>:' . esc_html(wp_trim_words(get_the_content(), 20)) . '</li>';
    }
    echo '</ul>';
    wp_reset_postdata();
    $html = ob_get_clean();
    wp_send_json_success($html);
  } else {
    wp_send_json_success('<p>履歴はありません。</p>');
  }
}
add_action('wp_ajax_load_user_inquiries', 'ajax_load_user_inquiries');
nonce検証を必ず行う
このハンドラーは読み取り専用(自分の問い合わせ履歴を返すだけ)ですが、check_ajax_referer()によるnonce検証を省略しないようにしましょう。将来的に処理内容が変わった場合の事故を防ぐ意味でも、Ajaxハンドラーには常にnonce検証を組み込むのが基本です。

HTML側に表示領域を設置する

フロントエンドテンプレートに以下のHTMLを記述して、Ajaxで取得した履歴を表示します。

表示領域のHTML
<div id="user-inquiry-list">読み込み中...</div>

よくある質問(FAQ)

Qカスタム投稿タイプのデータをAjaxで取得して表示する基本実装は?
Awp_localize_script()で渡したnonceとajax_urlを使ってjQuery.ajax()でリクエストを送信し、PHPのwp_ajax_get_custom_postsハンドラーでcheck_ajax_referer()による検証後にWP_Queryを実行してHTMLをwp_send_json_success()で返します。
QAjaxで返すHTMLとJSONどちらが良いですか?
AHTMLを返す方がJavaScript側の実装が簡単でパフォーマンスも良好です。複雑なUIやSPAではJSON(データのみ)を返してJavaScript側でHTMLを生成します。データの再利用性が高い場合はJSON推奨です。
QAjaxの問い合わせ結果をLocalStorageでキャッシュするには?
AレスポンスをlocalStorage.setItem(cacheKey, JSON.stringify(data))で保存し、次回リクエスト前にlocalStorage.getItem(cacheKey)を確認します。有効期限チェックのためタイムスタンプも一緒に保存します。個人情報を含むデータをキャッシュする場合はログアウト時のクリアも忘れずに。

まとめ

このように、非公開のカスタム投稿タイプとAjaxを組み合わせることで、ログインユーザーにだけ問い合わせ履歴を動的に表示する機能を簡単に実装できます。セキュリティを担保しつつ、ユーザーの利便性も高められるため、顧客サポートやマイページ機能に最適です。