Загрузка постов. Пагинация

Урок 4

Зарегистрируйтесь или войдите и получите бесплатный доступ к первому уроку курса.

Урок 4

Постраничная навигация с асинхронной подгрузкой постов в WordPress. Бесконечный скролл

В этом уроке я расскажу вам не только, как создать кнопку «Загрузить ещё» для постов на главной и в категориях, но мы также рассмотрим, как сделать загрузку постов при скролле и при этом сохраним пагинацию для SEO.

Чтобы скачать готовый код из этого урока, вам нужно купить курс.

Вот пример того, что у нас получится в ходе этого урока:

Работать будем со стандартной темой TwentyTwentyOne, во-первых, эта тема довольно простая и будет нетрудно разобраться в коде, во-вторых, вы всегда можете установить её прямо из админки из репозитория тем WordPress.

Что мы попробуем сделать в этом посту?

  • Загрузку постов при нажатии на кнопку «Загрузить ещё».
  • Бесконечную загрузку, т е посты будут подгружаться автоматически при прокрутке страницы.
  • Сделаем так, чтобы подгрузка постов работала для рубрик, меток и любых архивов таксономий (только на видео).
  • Сделаем динамическую пагинацию, показывающую текущую страницу после подгрузки постов (только на видео).

Шаг 1. Добавление кнопки «Загрузить ещё»

Для начала нам надо найти файл, в котором добавляется постраничная навигация. В TwentyTwentyOne это два файла – index.php для главной страницы сайта, где выводятся посты блога и archive.php – для меток и рубрик.. Если вы не понимаете, в каком файле надо искать в вашей теме, рекомендую взглянуть на этот туториал.

Если же вы решили использовать какую-то из стандартных тем (как я), то напоминаю, что для изменений желательно использовать дочерние темы (это же я и делаю в видео).

Найдите соответствующее место в шаблоне за пределами цикла while, то есть после того, как заканчивается вывод постов (в TwentyTwentyOne это место практически сразу после endwhile) и вставляем туда код:

<div id="loadmore" style="text-align:center;"><a href="#" class="button">Загрузить ещё</a></div>

Понятно, нам нужно учесть некоторые моменты, чтобы кнопка отображалась корректно, а именно:

  • Если это последняя страница с постами, то кнопку выводить не нужно.
  • Если количество постов в данной рубрике меньше, чем количество, установленное в Настройки > Чтение, то кнопку не отображаем также.

Это решается следующими условиями:

global $wp_query;
 
// текущая страница
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// максимум страниц
$max_pages = $wp_query->max_num_pages;
 
// если текущая страница меньше, чем максимум страниц, то выводим кнопку
if( $paged < $max_pages ) {
	// тут выводим кнопку
}

Кроме того, я предлагаю добавить на кнопку data-атрибут, чтобы передавать в обработчик информацию о том, на какой странице мы находимся в данный момент и какую страницу нужно загрузить.

global $wp_query;
 
// текущая страница
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
// максимум страниц
$max_pages = $wp_query->max_num_pages;
 
// если текущая страница меньше, чем максимум страниц, то выводим кнопку
if( $paged < $max_pages ) {
	echo '<div id="loadmore" style="text-align:center;">
		<a href="#" data-max_pages="' . $max_pages . '" data-paged="' . $paged . '" class="button">Загрузить ещё</a>
	</div>';
}

Также на кнопку я добавил класс .button, который стилизует её для темы TwentyTwentyOne.

Успешным выполнением первого шага будет считаться вот такая кнопка, которая должна будет появиться на странице всех ваших записей, но имейте ввиду, что если записей недостаточно для двух страниц, то кнопки не будет, для этого либо создайте больше записей, либо перейдите в Настройки > Чтение и измените количество отображаемых на странице записей там.

кнопка AJAX-загрузки постов в WordPress

Самый легкий шаг позади.

Шаг 2. Подключение скриптов

Документация функций wp_enqueue_script() и get_stylesheet_directory_uri() в помощь. Про подключение скриптов я писал часто и подробно, поэтому сейчас на этом останавливаться не будем, если есть проблемы — смотрите документацию. А этот код — в functions.php дочерней темы.

add_action( 'wp_enqueue_scripts', 'true_loadmore_scripts' );
 
function true_loadmore_scripts() {
	wp_enqueue_script( 'jquery' ); // в TwentyTwentyOne он не подключен по умолчанию
 
 	wp_enqueue_script( 
		'true_loadmore', 
		get_stylesheet_directory_uri() . '/loadmore.js', 
		array( 'jquery' ),
		time() // не кэшируем файл, убираем эту строчку после завершение разработки
	);
}

Также нам понадобится передать в loadmore.js динамический адрес обработчика AJAX в WordPress, поэтому мы немного модифицируем наш код, добавив в него функцию wp_localize_script().

add_action( 'wp_enqueue_scripts', 'true_loadmore_scripts' );
 
function true_loadmore_scripts() {
	wp_enqueue_script( 'jquery' ); // в TwentyTwentyOne он не подключен по умолчанию
 
 	wp_register_script( 
		'true_loadmore', 
		get_stylesheet_directory_uri() . '/loadmore.js', 
		array( 'jquery' ),
		time() // не кэшируем файл, убираем эту строчку после завершение разработки
	);
 
	wp_localize_script( 
		'true_loadmore', 
		'misha', 
		array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) )
	);
 
	wp_enqueue_script( 'true_loadmore' );
}

Шаг 3. Скрипт асинхронной загрузки

Вы ещё не создали файл loadmore.js в папке с темой? Давайте создадим его и добавим туда следующий код:

jQuery(function($){
 
	// определяем в переменные кнопку, текущую страницу и максимальное кол-во страниц
	var button = $( '#loadmore a' ),
	    paged = button.data( 'paged' ),
	    maxPages = button.data( 'max_pages' );
 
	button.click( function( event ) {
 
		event.preventDefault(); // предотвращаем клик по ссылке
 
		$.ajax({
			type : 'POST',
			url : misha.ajax_url, // получаем из wp_localize_script()
			data : {
				paged : paged, // номер текущей страниц
				action : 'loadmore' // экшен для wp_ajax_ и wp_ajax_nopriv_
			},
			beforeSend : function( xhr ) {
				button.text( 'Загружаем...' );
			},
			success : function( data ){
 
				paged++; // инкремент номера страницы
				button.parent().before( data );
				button.text( 'Загрузить ещё' );
 
				 // если последняя страница, то удаляем кнопку
				if( paged == maxPages ) {
					button.remove();
				}
 
			}
 
		});
 
	} );
});

Я постарался сделать этот код максимально простым, дополнительными переменными усложнять его не стал. Если вы хотя бы немного разбираетесь в jQuery, то у вас не возникнет с ним никаких проблем. Даже если не разбираетесь, но сделаете всё по инструкции, то всё тоже будет ок.

Шаг 4. Обработчик PHP, вывод постов

Этот код также отправляется в файл functions.php. Если он вам непонятен, читайте подробнее про циклы, WP_Query и query_posts().

add_action( 'wp_ajax_loadmore', 'true_loadmore' );
add_action( 'wp_ajax_nopriv_loadmore', 'true_loadmore' );
 
function true_loadmore() {
 
	$paged = ! empty( $_POST[ 'paged' ] ) ? $_POST[ 'paged' ] : 1;
	$paged++;
 
	$args = array(
		'paged' => $paged,
		'post_status' => 'publish'
	);
 
	query_posts( $args );
 
	while( have_posts() ) : the_post();
 
		get_template_part( 'template-parts/content/content', get_theme_mod( 'display_excerpt_or_full_post', 'excerpt' ) );
 
	endwhile;
 
	die;
 
}

Бесконечная загрузка постов при прокрутке страницы

Суть в том, что вы просто скроллите страницу вниз, а новые посты подгружаются по мере её прокрутки. Насколько я помню, впервые такая штука появилась у твиттера (могу ошибаться, поправьте, если я не прав), а потом уже все стянули её оттуда.

Скажу честно — заразная вещь. Те, кто сидят на сайте вконтакте, понимают это прекрасно. Так что, если у вас новостной сайт, тогда этот способ загрузки постов просто «must have».

Если вы сделали все предыдущие шаги из поста и дошли до этого момента — тогда отлично, добавим некоторые изменения для шагов 1 и 3.

Содержимое файла loadmore.js изменится и будет следующим:

jQuery(function($){
	$(window).scroll(function(){
		var bottomOffset = 2000,  // отступ от нижней границы сайта, до которого должен доскроллить пользователь, чтобы подгрузились новые посты
		    button = $( '#loadmore a' ),
		    paged = button.data( 'paged' ),
		    maxPages = button.data( 'max_pages' );
 
		if( $(document).scrollTop() > ($(document).height() - bottomOffset) && !$('body').hasClass('loading')){
			$.ajax({
				type : 'POST',
				url : misha.ajax_url,
				data : {
					paged : paged,
					action : 'loadmore' 
				},
				beforeSend: function( xhr){
					$('body').addClass('loading');
				},
				success:function(data){
					if( data ) {
						paged++;
						button.parent().before( data );
						$('body').removeClass('loading');
					}
				}
			});
		}
	});
});

Надеюсь, что не запутал вас. Если возникнут трудности то не забывайте про видео.

Динамическая пагинация при асинхронной подгрузке постов

Очень многие из моих учеников сталкиваются с тем, что им надо сохранить пагинацию. То есть, чтобы были и кнопка «Загрузить ещё» и пагинация ссылками. Причём сама пагинация должна динамически изменяться в зависимости от того, какие посты подгружены и на какой странице мы находимся после этого.

Пагинация подробно рассмотрена на видеоуроке 🙂

Купить курс
  • 7 видеоуроков
  • Доступ к теме курса с готовым кодом после каждого урока
  • Единоразовый платёж
  • Доступ навсегда
  • Уроки актуальны в 2024-м году
4000 р

Нажав на кнопку, вы соглашаетесь c условиями предоставления услуг и с обработкой персональных данных.