カスタム投稿一覧画面で、「もっと読み込む」ボタンをクリック後、ページ遷移なしで記事を追加で読み込む方法を残します。
なるべく余計なコードを書かずに応用が効くように整理しました。
今回はカスタム投稿一覧(archive-xxx.php)を例に進めますが、トップページや固定ページでももちろん可能です。
ちなみにAjaxはJavascript、jQueryどちらでも記載できますが、この記事ではjQueryの方を採用してます。(なるべくjQuery脱却していきたいのですが。。)
今回は、
カスタム投稿タイプがnews、記事一覧初期表示の件数は6、追加で読み込む件数は3
という例で進めます。
コードを記載するファイルは下記3つ。
archive-news.php(もっと読み込むボタンを設定したいページ。なんでもOK)
javascriptファイル(wordpressで読み込んでるjsファイル)
functions.php
カスタム投稿の場合は、"news"部分だけ変えていただければコピペで動作するコードになってます。
デフォルト機能の「投稿」の場合は、処理の読み替えが発生しますのでご了承ください。
処理の流れのイメージ図は下記。
これを最初に頭に入れておくと各ファイルで何をしているか理解しやすいと思います。
上記を見て分かるように、javascriptはあくまでクッション処理であって、
実行したい処理(サーバ処理)はfunctions.phpに記載することになります。
archive-news.php
<?php get_header(); ?>
<main>
<?php if (have_posts()): ?>
<ul>
<?php while (have_posts()): the_post(); ?>
<li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
<?php endwhile; ?>
</ul>
<!-- カスタム投稿全件数取得 -->
<?php global $wp_query; $count = $wp_query->found_posts;?>
<!-- この部分がajaxで追加読み込みする箇所 -->
<!-- javascript側に渡したい値は、data属性を使って指定 -->
<ul class="load" data-count="<?php echo $count; ?>"
data-post-type="news" ></ul>
<!-- 初期表示件数が全件数より少ない場合、もっと読み込むボタンを表示 -->
<?php if($count > 6): ?>
<button class="more_btn">もっと読み込む</button>
<?php endif; ?>
<?php endif; ?> <!-- END if (have_posts()) -->
</main>
<?php get_footer(); ?>
カスタム投稿全件数は、初期表示の「もっと読み込む」ボタンを表示するかどうかの判定で使用します。
さらにデータを読み込んだ後で、再度ボタン表示するかどうかのチェックに使用するため、javascriptにdata属性として渡しておきます。
javascriptファイル
jQuery(function($){
let now_post_num = 6; // 現在表示されている件数
let get_post_num = 3 // もっと読み込むボタンで取得する件数
//archive側で設定したdata属性の値を取得
let load = $(".load");
let post_type = load.data("post-type");
let all_count = load.data("count"); //カスタム投稿の全件数
//admin_ajaxにadmin-ajax.phpの絶対パス指定(相対パスは失敗する)
let host_url = location.protocol + "//" + location.host;
let admin_ajax = host_url + '/wp-admin/admin-ajax.php';
$(document).on("click", ".more_btn", function () {
//読み込み中はボタン非表示
$('.more_btn').remove();
//ajax処理。data{}のactionに指定した関数を実行、完了後はdoneに入る
$.ajax({
type: 'POST',
url: admin_ajax,
data: {
'action' : 'my_ajax_action', //functions.phpで設定する関数名
'now_post_num': now_post_num,
'get_post_num': get_post_num,
'post_type': post_type,
},
})
.done(function(data){ //my_ajax_action関数で取得したデータがdataに入る
//.loadにデータを追加
load.append(data);
//表示件数を増やす
now_post_num = now_post_num + get_post_num;
//まだ全件表示されていない場合、ボタンを再度表示
if(all_count > now_post_num) {
load.after('<button class="more_btn">もっと読み込む</button>');
}
})
.fail(function(){
alert('エラーが発生しました');
})
});
});
WordPressの場合は、urlに指定するファイル(admin-ajax.php)があらかじめ用意されています。
このファイルを絶対パスで設定すること。
ajaxではurlで指定したファイルにアクセスし、さらにdataのaction値で設定した関数を実行します。
この関数自体はfunctions.php側でアクションフックするため、functions.phpで記載する処理を実行できるという仕組み。
functions.php側に渡したいデータはdata{}の中に指定しておきます。
functions.php
/* カスタム投稿一覧の初期表示件数を設定 */
function my_custom_query_vars( $query ) {
if ( !is_admin() && $query->is_main_query()) {
if ( is_post_type_archive('news') ) {
$query->set( 'posts_per_page' , 6 );
}
}
return $query;
}
add_action( 'pre_get_posts', 'my_custom_query_vars' );
/* ajax処理 */
function my_ajax(){
global $post;
$args = array(
'posts_per_page' => $_POST["get_post_num"], // 追加で表示する件数
'offset' => $_POST["now_post_num"], //既に表示済みの件数は除外
'post_type' => $_POST["post_type"],
'orderby' => 'date', //日付で並び替え
'order' => 'DESC',
);
$my_posts = get_posts($args);
foreach ($my_posts as $post) : setup_postdata($post);
echo '<li class="item">';
echo '<a href="'.get_the_permalink().'">'.get_the_title().'</a>';
echo '</li>';
endforeach; wp_reset_postdata();
wp_die();
}
add_action( 'wp_ajax_my_ajax_action', 'my_ajax' );
add_action( 'wp_ajax_nopriv_my_ajax_action', 'my_ajax' );
javascriptのdata{}で指定した値を、$_POSTで受け取り、実行したい処理を書くだけです。
カスタム投稿取得では、WP_Queryがoffsetプロパティが使えないみたいなので、get_postsで取得しています。
add_actionが二つあるのはそれぞれログイン済ユーザーかそうでないかで処理が分かれるため。
特にこだわりがなければ二つ書けばOKです。
function名がxxxの場合はadd_actionは下記になります。
add_action( 'wp_ajax_xxx_action', 'xxx' );
add_action( 'wp_ajax_nopriv_xxx_action', 'xxx' );