WordPress | Ajaxで非同期に記事データを追加で読み込む方法

アーカイブページの記事一覧で「もっと見る」や「View More」のようなボタンを置いてクリック時にページ遷移せず次ページの記事一覧データをAjaxで読み込み追加する方法のメモ。

functions.php に設定

admin-ajax.php までのURLを宣言

Ajax を利用出来るように JavaScript のグローバル変数で admin-ajax.php までのURLを追加します。

<?php
/**
 * Ajaxを利用出来るよう admin-ajax.php までのURLを追加
 */
function cf_add_ajaxurl()
{
  $url = admin_url( 'admin-ajax.php' );
?>
<script>
var ajaxurl = '<?php echo $url; ?>';
</script>
<?php
}
add_action( 'wp_head', 'cf_add_ajaxurl', 1 );

Moreボタンクリック時に追加データを取得して返す

Moreボタンがクリックされた際に Ajax でPOST送信で指定された関数 cf_ajax_get_more_post() を実行して条件に合う追加読み込み用の投稿データを取得して整形したHTMLデータを返します。

/**
 * Ajax
 * Moreボタンクリック時に対象の投稿データを取得してHTMLデータを返す
 */
function cf_ajax_get_more_post()
{
    // POSTデータ取得
    $cur_cnt   = $_POST["cur_cnt"];   // 表示済み件数
    $tgt_cnt   = $_POST["tgt_cnt"];   // Moreボタンで取得する件数
    $post_type = $_POST["post_type"]; // 投稿タイプ
    $taxonomy  = $_POST["taxonomy"];  // タクソノミー
    $term_slug = $_POST["term_slug"]; // タームのスラッグ

    // 取得条件パラメーター
    $args = [
        'posts_per_page' => $tgt_cnt,   // 追加表示する件数
        'offset'         => $cur_cnt,   // 表示済み件数を除外 
        'post_type'      => $post_type, // 投稿タイプ
        'orderby'        => 'date',     // 日付でソート
        'order'          => 'DESC',     // 降順
    ];

    // タクソノミーとタームスラッグの指定がある場合、tax_query を追加
    if ( $taxonomy && $term_slug ) {
        $args['tax_query'] = array(
            array(
                'taxonomy' => $taxonomy,
                'field'    => 'slug',
                'terms'    => array($term_slug)
            )
        );
    }

    // 投稿データ取得
    $query = new WP_Query($args);

    // 
    $html = "";
    while ($query->have_posts()) { $query->the_post();
        $post_id = get_the_ID();
        $title   = get_the_title( $post_id );
        $link    = get_the_permalink( $post_id );

        // 出力用HTML
        $html .= '<a href="'.$link.'">';
        $html .= '<p>'.$title.'</p>';
        $html .= '</a>';

    }
    wp_reset_postdata();

    // HTML表示
    echo $html;
    wp_die();
}
add_action( 'wp_ajax_cf_ajax_get_more_post', 'cf_ajax_get_more_post' );        // ログインユーザー用
add_action( 'wp_ajax_nopriv_cf_ajax_get_more_post', 'cf_ajax_get_more_post' ); // ログアウトユーザー用

アーカイブページに設定

各種変数宣言

メインループやAjax処理で利用するWordPress側へ渡す変数を宣言します。

<?php
global $wp_query;
// 投稿の全件数
$all_cnt = $wp_query->found_posts;
// 表示済み件数
$cur_cnt = $wp_query->post_count;
// Moreボタンで取得する件数
$tgt_cnt  = 3;
// 投稿タイプ
$post_type = "post";
// タクソノミー
$taxonomy = "category";
// タームのスラッグ
$term_slug = "";
?>

data属性に変数セット

data属性に上記で宣言した変数の値をセットします。ループ下に Moreボタンを配置します。

<?php if (have_posts()) : ?>

<div 
  class="more-post-load" 
  data-all-cnt="<?php echo $all_cnt; ?>" 
  data-cur-cnt="<?php echo $cur_cnt; ?>" 
  data-tgt-cnt="<?php echo $tgt_cnt; ?>" 
  data-post-type="<?php echo $post_type; ?>" 
  data-taxonomy="<?php echo $taxonomy; ?>" 
  data-term-slug="<?php echo $term_slug; ?>"
>
  <?php while (have_posts()) : the_post(); ?>
    <a href="<?php the_permalink(); ?>">
      <p><?php the_title(); ?></p>
    </a>
  <?php endwhile; ?>
</div>

<div class="more-btn"><a>More</a></div>

<?php endif; ?>

Moreボタンクリック時

Moreボタンがクリックされた際に実行される処理を記述します。data { … } の action で指定した functions.php に宣言した関数 cf_ajax_get_more_post を実行し返ってきたHTMLデータをリストの最後に追加します。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
jQuery(function($) {
  // MoreボタンHTML
  let btn_html = '<div class="more-btn"><a>More</a></div>';

  // data属性値を取得
  let load      = $(".more-post-load");   // 
  let cur_cnt   = load.data("cur-cnt");   // 表示済み件数
  let tgt_cnt   = load.data("tgt-cnt");   // Moreボタンで取得する件数
  let post_type = load.data("post-type"); // 投稿タイプ
  let taxonomy  = load.data("taxonomy");  // タクソノミー
  let term_slug = load.data("term-slug"); // タームのスラッグ 
  let all_cnt   = load.data("all-cnt");   // 投稿の全件数

  // 
  $(document).on("click", ".more-btn", function() {

    // Moreボタン削除
    $('.more-btn').remove();

    // WP側の関数を実行
    // ※ cf_ajax_get_more_post は functions.php 等に追加
    $.ajax({
        type: 'POST',
        url: ajaxurl,
        data: {
          'action': 'cf_ajax_get_more_post',
          'cur_cnt': cur_cnt,
          'tgt_cnt': tgt_cnt,
          'post_type': post_type,
          'taxonomy': taxonomy,
          'term_slug': term_slug,
        },
      })
      .done(function(data) {
        // 一覧の最後に取得した投稿データを追加する
        load.append(data);

        // 表示済み件数を増やす
        cur_cnt = cur_cnt + tgt_cnt;

        // Moreボタンを再度表示
        // ※ 表示済み件数より全件数が多い場合
        if (all_cnt > cur_cnt) {
          load.append(btn_html);
        }
      })
      .fail(function() {
        // エラー
        console.log('エラー');
      })
  });
});
</script>

動作環境情報

"エックスサーバー" スタンダード(旧X10)
"PHP" 8.0.25
"MariaDB" 10.5
"WordPress" 6.1.1
"jQuery" 3.6.1

コメント

タイトルとURLをコピーしました