WordPress. Несколько циклов

В этом разделе рассматривается расширенное использование циклов. Это немного технично, но пусть это вас не пугает. Мы начнем с простого примера и будем двигаться дальше. Проявив немного здравого смысла, терпения и энтузиазма, вы тоже сможете создавать циклы под любые ваши нужды.

Во-первых, зачем использовать несколько циклов? В общем, ответ заключается в том, что вы можете захотеть сделать что-то с одной группой сообщений и сделать что-то другое с другой группой сообщений, но отобразить обе группы на одной странице . «Что-то» может означать почти что угодно; вы ограничены только вашими навыками PHP и вашим воображением.

Мы рассмотрим примеры ниже, но сначала вы должны прочитать об основах. Взгляните на основной цикл. Его структура такова:

<?php if ( have_posts() ) : ?>
	<?php while ( have_posts() ) : the_post(); ?>    
	<!-- do stuff ... -->
	<?php endwhile; ?>
<?php endif; ?>

На английском (PHP-типы и люди, знакомые с кодом, могут пропустить ниже) приведенное выше будет читаться так: Если мы собираемся отображать сообщения, то получайте их по одному. Для каждого сообщения в списке отображайте его в соответствии с некоторым шаблоном. Когда дойдём до последнего поста, обработайте его и остановить цикл. Строка (строки) работы зависит от шаблона.

Небольшое отступление о том, что делать : в этом примере это просто заполнитель для кода, который определяет, как форматировать и отображать каждый пост на странице. Этот код может меняться в зависимости от того, как вы хотите, чтобы ваш WordPress выглядел. Если вы посмотрите на файл index.php темы Кубрика, то в разделе «Делать что-то» будет все ниже:

<?php while ( have_posts() ) : the_post(); ?>
<?php comments_popup_link( 'No Comments »', '1 Comment »', '% Comments »' ); ?>

Пояснение: have_posts() и the_post() — это удобные оболочки вокруг глобального объекта $wp_query , в котором и происходит все действие. $wp_query вызывается в заголовке блога и передает аргументы запроса, поступающие через GET и PATH_INFO . $wp_query принимает аргументы, строит и выполняет запрос к БД, результатом которого является массив сообщений. Этот массив сохраняется в объекте, а также возвращается обратно в заголовок блога, где он помещается в глобальный массив $posts (для обратной совместимости со старыми циклами сообщений).

Как только WordPress завершит загрузку заголовка блога и спустится в шаблон, мы придем к циклу публикации. Функция have_posts() просто вызывает метод $wp_query->have_posts() , которая проверяет счетчик циклов, чтобы узнать, остались ли какие-либо сообщения в массиве сообщений. И the_post() вызывает $wp_query->the_post() , который увеличивает счетчик циклов и устанавливает глобальную переменную $post , а также все глобальные данные поста. Как только мы исчерпаем цикл, функция have_posts() вернет false, и мы закончим.

Примеры циклов

Ниже приведены три примера использования нескольких циклов. Ключом к использованию нескольких циклов является то, что $wp_query можно вызвать только один раз. Чтобы обойти это, можно повторно использовать запрос, вызвав rewind_posts() или создав новый объект запроса. Это рассматривается в примере 1. В примере 2 рассматривается использование переменной для хранения результатов запроса. Наконец, «несколько циклов в действии» объединяет множество идей, чтобы задокументировать один из способов использования нескольких циклов для продвижения сообщений определенной категории на главной странице вашего блога.

Пример 1

Чтобы повторить тот же запрос во второй раз, вызовите rewind_posts() . Это сбросит счетчик циклов и позволит вам выполнить еще один цикл.

<?php rewind_posts(); ?>
 
<?php while ( have_posts() ) : the_post(); ?>
	<!-- Do stuff... -->
<?php endwhile; ?>

Если вы закончили работу с сообщениями в исходном запросе и хотите использовать другой запрос, вы можете повторно использовать объект $wp_query, вызвав query_posts() , а затем вернуться к циклу. query_posts () выполнит новый запрос, создаст новый массив сообщений и сбросит счетчик циклов.

// Get the last 10 posts in the special_cat category.
<?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( have_posts() ) : the_post(); ?>
	<!-- Do special_cat stuff... -->
<?php endwhile; ?>

Если вам нужно сохранить исходный запрос, вы можете создать новый объект запроса.

<?php $my_query = new WP_Query( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
	<!-- Do special_cat stuff... -->
<?php endwhile; ?>

Объект запроса my_query используется, потому что вы не можете использовать глобальные функции have_posts() и the_post(), так как они оба используют $wp_query . Вместо этого вызовите новый объект $my_query .

Пример 2

Другая версия использования нескольких циклов использует другой способ обойти невозможность использования have_posts() и the_post() . Чтобы решить эту проблему, вам нужно сохранить исходный запрос в переменной, а затем переназначить его с помощью другого цикла. Таким образом, вы можете использовать все стандартные функции, которые полагаются на все глобальные переменные.

// going off on my own here
<?php $temp_query = clone $wp_query; ?>
<!-- Do stuff... -->

<?php query_posts( 'category_name=special_cat&posts_per_page=10' ); ?>

<?php while ( have_posts() ) : the_post(); ?>
	<!-- Do special_cat stuff... -->
<?php endwhile; ?>

// now back to our regularly scheduled programming
<?php $wp_query = clone $temp_query; ?>

Несколько циклов в действии

Лучший способ понять, как использовать несколько циклов, — показать пример их использования. Возможно, наиболее распространенное использование нескольких циклов — это отображение двух (или более) списков сообщений на одной странице. Это часто делается, когда веб-мастер хочет показать не только самый последний написанный пост, но и посты из определенной категории.

Оставив в стороне все проблемы с форматированием и CSS, предположим, что мы хотим иметь два списка сообщений. Один, в котором будут перечислены самые последние сообщения (стандартные 10 последних добавленных сообщений), а другой будет содержать только одно сообщение из категории «избранные». Сообщения в категории «избранные» должны отображаться первыми, а затем следует второй список сообщений (стандартный). Подвох в том, что ни один пост не должен появляться в обеих категориях.

Шаг 1. Получите только один пост из категории «Избранное».

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
	<!-- Do stuff... -->
<?php endwhile; ?>

Происходит тут следующее:

Устанавливаем $my_query равным результату запроса всех сообщений, в которых категория названа избранной, и выбираем только одно сообщение. Кроме того, устанавливаем переменную $do_not_duplicate равной идентификационному номеру возвращаемого сообщения. Напомним, что в строке «Do stuff» подразумеваются все параметры форматирования, связанные с полученным сообщением.

Обратите внимание, что на следующем шаге нам понадобится значение $do_not_duplicate , чтобы одно и то же сообщение не отображалось в обоих списках.

Шаг 2 . Второй цикл, получить X последних сообщений (кроме одного).

Следующий код получает X последних сообщений (как определено в настройках WordPress), сохраняет сообщение, уже отображаемое в первом цикле, и отображает их в соответствии с Do stuff .

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue;?>
	<!-- Do stuff... -->
<?php endwhile; endif; ?>

Тут происходит следующее: Получите все сообщения. Сообщение с идентификатором равным $do_not_duplicate, пропустить ( continue), все остальные сообщения отобразить в соответствии с Do stuff . Кроме того, обновите кеш, чтобы плагины тегов и ключевых слов работали нормально. Напомним, переменная $do_not_duplicate содержит идентификатор уже отображаемого поста.

Конечный результат

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>
	<!-- Do stuff... -->
<?php endwhile; ?>
	<!-- Do other stuff... -->
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue; ?>
	<!-- Do stuff... -->
<?php endwhile; endif; ?>

Конечным результатом будет страница с двумя списками. Первый список содержит только один пост — самый последний пост из категории «избранное». Второй список будет содержать X последних сообщений (как определено в настройках WordPress), за исключением сообщения, которое уже отображается в первом списке. Таким образом, как только сообщение с функцией будет заменено новым, предыдущая функция будет отображаться в разделе стандартного списка сообщений ниже (в зависимости от того, сколько сообщений вы выберете для отображения, и от частоты публикации). Этот метод (или аналогичный) использовался многими в сочетании со знанием иерархии шаблонов для создания другого вида для home.php и index.php.

Примечание для нескольких сообщений в первой категории

Если posts_per_page=2 или больше, вам нужно будет немного изменить код. Переменная $do_not_duplicate должна быть преобразована в массив, а не в одно значение. В противном случае первый цикл завершится и переменная $do_not_duplicate будет равна только идентификатору последнего сообщения. Это приведет к дублированию сообщений во втором цикле. Чтобы устранить проблему, замените:

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=1' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate = $post->ID; ?>

на

<?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=2' );
while ( $my_query->have_posts() ) : $my_query->the_post();
$do_not_duplicate[] = $post->ID; ?>

Обратите внимание, что «posts_per_page» может быть любым числом. Это превращает $do_not_duplicate в массив. Затем замените

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( $post->ID == $do_not_duplicate ) continue; ?>

на

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); 
if ( in_array( $post->ID, $do_not_duplicate ) ) continue; ?>

Где вы продолжаете шаблон для любого значения posts_per_page, равного (2 в данном случае).

В качестве альтернативы вы можете передать весь массив $do_not_duplicate в $wp_query , и будут возвращены только записи, соответствующие вашим критериям:

<?php query_posts(array('post__not_in' => $do_not_duplicate));
if ( have_posts() ) : while ( have_posts() ): the_post(); ?>

Обратите внимание, что вместо строки параметр запроса был ассоциативным массивом, задающим опцию post__not_in .

Вложенные циклы

Вложенные циклы означают, что вы выполняете второй цикл до завершения первого. Это может быть полезно, например, для отображения списка сообщений с коротким кодом .

$my_query = new WP_Query( 'cat=3' );
if ( $my_query->have_posts() ) { 
	while ( $my_query->have_posts() ) { 
		$my_query->the_post();
		the_content();
	}
}
wp_reset_postdata();

Необходимо сбросить данные основного цикла после вложенного цикла, чтобы некоторые глобальные переменные снова имели правильные значения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *