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

Если на моём сайте вы перейдёте на страницу Блог или в какую-нибудь рубрику, то в самом низу страницы, наряду с обычной постраничной навигацией, вы увидите кнопку Загрузить ещё, которая позволяет подгружать следующие посты без обновления страницы.

Скажу прямо, на моём сайте используется в некоторой степени шаманский способ навигации по страницам — эту навигацию я разрабатывал давно и возможно в те времена ещё не был так хорош в PHP и jQuery. Теперь же я вам покажу более правильный и эффективный способ реализации постраничной навигации с возможностью асинхронной загрузки новых постов. То есть в код моего сайта можете не смотреть, а если у вас появятся вопросы, тогда лучше задайте их в комментариях к этому посту, отвечу обязательно.

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

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

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

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

Для начала нам надо найти файл, в котором добавляется постраничная навигация. В TwentyTen этот файл — loop.php. Открываем его и находим два блока <div id="nav-below"> и <div id="nav-above">. В этих блоках вставляются ссылки перехода на следующую или предыдущую страницу с постами.

Последний из них (тот, который находится в начале файла) нам больше не понадобится (ведь кнопка загрузки новых постов будет только внизу), поэтому удаляем его вместе со стоящим перед ним php-условием. Удаляем, сохраняем, смотрим сайт — ошибок нет? Тогда двигаемся дальше.

Нижний блок мы теперь заменим на:

<?php if (  $wp_query->max_num_pages > 1 ) : ?>
	<script>
	var ajaxurl = '<?php echo site_url() ?>/wp-admin/admin-ajax.php';
	var true_posts = '<?php echo serialize($wp_query->query_vars); ?>';
	var current_page = <?php echo (get_query_var('paged')) ? get_query_var('paged') : 1; ?>;
	var max_pages = '<?php echo $wp_query->max_num_pages; ?>';
	</script>
	<div id="true_loadmore">Загрузить ещё</div>
<?php endif; ?>
ajaxurl
Это обработчик AJAX-запросов в WordPress.
true_posts
Сериализованный массив, содержащий все необходимые параметры запроса, является свойством класса WP_Query.
current_page
Номер текущей страницы.

А теперь немного стилей, которые мы добавим на нашу кнопку, чтобы она круто выглядела (стили можно вставить в стандартный style.css в папке с темой).

#true_loadmore{
	background: #000; /* черный фон */
	color: #FFF; /* белый цвет текста */
	padding: 5px; /* отступы от границ 5px */
	text-align: center; /* выравнивание текста по центру */
	-moz-border-radius: 4px; 
	-webkit-border-radius: 4px;
	border-radius: 4px; /* закругление углов */
	margin: 20px 0; /* отступы сверху и снизу от кнопки */
	cursor:pointer; /* курсор мыши при наведении такой же, как при наведении на ссылку */
}

На данный момент имеем:

Кнопка асинхронной загрузки постов

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

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

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

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

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

jQuery(function($){
	$('#true_loadmore').click(function(){
		$(this).text('Загружаю...'); // изменяем текст кнопки, вы также можете добавить прелоадер
		var data = {
			'action': 'loadmore',
			'query': true_posts,
			'page' : current_page
		};
		$.ajax({
			url:ajaxurl, // обработчик
			data:data, // данные
			type:'POST', // тип запроса
			success:function(data){
				if( data ) { 
					$('#true_loadmore').text('Загрузить ещё').before(data); // вставляем новые посты
					current_page++; // увеличиваем номер страницы на единицу
					if (current_page == max_pages) $("#true_loadmore").remove(); // если последняя страница, удаляем кнопку
				} else {
					$('#true_loadmore').remove(); // если мы дошли до последней страницы постов, скроем кнопку
				}
			}
		});
	});
});

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

Шаг 4. Обработчик PHP

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?php
function true_load_posts(){
	$args = unserialize(stripslashes($_POST['query']));
	$args['paged'] = $_POST['page'] + 1; // следующая страница
	$args['post_status'] = 'publish';
	$q = new WP_Query($args);
	if( $q->have_posts() ):
		while($q->have_posts()): $q->the_post();
			/*
			 * Со строчки 13 по 27 идет HTML шаблон поста, максимально приближенный к теме TwentyTen.
			 * Для своей темы вы конечно же можете использовать другой код HTML.
			 */
			?>
			<div id="post-<?php echo $q->post->ID ?>" class="post-<?php echo $q->post->ID ?> hentry">
				<h2 class="entry-title"><a href="<?php the_permalink() ?>" rel="bookmark"><?php echo $q->post->post_title ?></a></h2>
				<div class="entry-meta">
					<span class="meta-prep meta-prep-author">Опубликовано</span> <span class="entry-date"><?php the_time('j M Y') ?></span></a>
					<span class="meta-sep">автором</span>
					<span class="author vcard"><?php the_author_link(); ?> </span>
				</div>
				<div class="entry-content"><p style="text-align: center;"><?php the_content() ?></p></div>
				<div class="entry-utility">
					<span class="cat-links">
					<span class="entry-utility-prep entry-utility-prep-cat-links">Рубрика:</span> <?php the_category(', '); ?></span>
					<span class="meta-sep">|</span>
					<span class="comments-link"><a href="<?php the_permalink() ?>#comments">Комментарии (<?php echo $q->post->comment_count ?>)</a></span>
				</div>
			</div>
			<?php
		endwhile;
	endif;
	wp_reset_postdata();
	die();
}
 
 
add_action('wp_ajax_loadmore', 'true_load_posts');
add_action('wp_ajax_nopriv_loadmore', 'true_load_posts');

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

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

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

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

Во-первых, кнопка Загрузить ещё нам больше не понадобится, поэтому немного изменим HTML-код:

<?php if (  $wp_query->max_num_pages > 1 ) : ?>
	<script id="true_loadmore">
	var ajaxurl = '<?php echo site_url() ?>/wp-admin/admin-ajax.php';
	var true_posts = '<?php echo serialize($wp_query->query_vars); ?>';
	var current_page = <?php echo (get_query_var('paged')) ? get_query_var('paged') : 1; ?>;
	</script>
<?php endif; ?>

Во-вторых, стили CSS нам тоже больше не нужны, если вы их добавляли, можете напрочь удалить.

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

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

Файл functions.php (это шаги 2 и 4) мы оставляем без изменений. Хотя в PHP-обработчике вы можете удалить строки с 31-й по 35-ю.

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

Миша Рудрастых Разработчик WordPress WooCommerce

Миша Рудрастых

Впервые познакомился с WordPress в 2009 году, и после двух лет мучений с Joomla и самописными движками это был просто бальзам на душу. С 2014 года меня можно встретить на WordCamp — официальной конфе по WP в Москве, иногда там выступаю. Также в настоящее время веду курсы по WordPress в Epic Skills в Питере.

Смотрите также