Codex

Interested in functions, hooks, classes, or methods? Check out the new WordPress Code Reference!

Цикл WordPress

Эта страница помечена как незавершённая. Вы можете помочь проекту, дополнив её.

Циклом называют PHP код, который отображает записи на страницах WordPress. WordPress обрабатывает им каждую запись, которую следует показать на текущей странице, и форматирует её так, как задано в теле Цикла. Любой HTML или PHP код, расположенный внутри Цикла, будет повторен для каждой записи.

Когда документация WordPress говорит про конкретные Тэги Шаблона или плагины, что "этот тэг используется внутри Цикла", то тэг будет повторен для каждой записи. Например, по умолчанию Цикл выводит для каждой записи следующую информацию:

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

Для первого знакомства с Циклом прочтите Цикл в Действии.

Использование Цикла

Цикл должен быть расположен в файле index.php и в любых других шаблонах, используемых для отображения записей.

Убедитесь, что включили вызов заголовка Шаблона (header.php) в верхней части Шаблонов вашей Темы. Если вы используете Цикл внутри собственного дизайна (и ваш дизайн не является шаблоном), установите WP_USE_THEMES в значение false:

<?php define('WP_USE_THEMES', false); get_header(); ?>

Цикл начинают этой строкой кода:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

и заканчивают так:

<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>

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

Стилизация Записей из различных Рубрик

Этот пример отображает для каждой записи её Заголовок, Рубрики и Содержимое. При этом Заголовок используется в качестве ссылки на Постоянный адрес записи.

Кроме того, записи из Рубрики с ID равным '3' получают особый класс стилей, чтобы поменять их внешний вид с помощью CSS. Для этого задействован Тэг Шаблона in_category().

Внимательно прочтите комментарии внутри HTML тэгов <!-- -->, чтобы разобраться, что делает каждая часть кода. Если вы используете данный пример на сайте, комментарии не будут отображаться в браузере.

 <!-- Начинаем Цикл. -->

 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

 
     <!-- Открываем блок div для очередной записи. -->
     <!-- При этом проверяем, относится ли текущая запись к рубрике 3. -->
     <!-- Если да, то присваиваем блоку класс стилей "post-cat-three". -->
     <!-- В противном случае блок получает класс "post". -->
 
     <?php if ( in_category('3') ) { ?>
         <div class="post-cat-three">
     <?php } else { ?>
         <div class="post">
     <?php } ?>
 
 
         <!-- Выводим Заголовок со ссылкой на постоянный адрес Записи. -->
         
         <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
 
 
         <!-- Отображаем время публикации в формате "Ноябрь 16, 2009". --> 
         <!-- Добавляем ссылку на другие записи этого же автора. --> 
 
         <small><?php the_time('F j, Y'); ?> by <?php the_author_posts_link(); ?></small>
 
 
         <!-- Показываем Содержимое Записи внутри ещё одного блока div. -->
 
         <div class="entry">
             <?php the_content(); ?>
         </div>
 
 
         <!-- Перечисляем Рубрики, к которым относится Запись, разделяя их запятыми. -->
 
         <p class="postmetadata"><?php _e( 'Posted in' ); ?> <?php the_category( ', ' ); ?></p>
 
 
     <!-- Закрываем блок div. -->
 
     </div> 
 
 
 <!-- Останавливаем обработку записей в Цикле (но есть ещё ключевое слово "else:" - смотрите далее). -->
 
 <?php endwhile; else: ?>

 
     <!-- В начале "if" проверил, существуют ли какие-либо записи для показа.  -->
     <!-- Теперь "else" говорит, что делать, если записей не оказалось. -->
 
     <p><?php esc_html_e( 'Sorry, no posts matched your criteria.' ); ?></p>
 
 
 <!-- ПОЛНОСТЬЮ останавливаем Цикл. -->
 
 <?php endif; ?>
 

Запомните: HTML код следует располагать за пределами тэгов <?php и ?>, а PHP код (в том числе простые фигурные скобки { } ) должен быть внутри тэгов <?php и ?>. Вы можете открывать и закрывать блоки PHP кода, чтобы добавлять в HTML код операторы if и else так, как показано в примере выше.

Исключение Записей из некоторых Рубрик

Этот пример может быть использован для исключения определенной Рубрики из обычного отображения. Он основан на предыдущем примере.

 <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

 <!-- Если запись находится в рубрике, которую мы хотим исключить, мы просто переходим к следующей записи. -->
 
<?php if (in_category('3')) continue; ?>
 
 <div class="post">
 
  <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
 
  <small><?php the_time('F jS, Y'); ?></small>
 
  <div class="entry">
    <?php the_content(); ?>
  </div>

  <p class="postmetadata">Posted in <?php the_category(', '); ?></p>
 </div> <!-- closes the first div box -->

 <?php endwhile; else: ?>
 <p>Sorry, no posts matched your criteria.</p>
 <?php endif; ?>

Запомните: Если вы используете этот пример для основной страницы, вы должны использовать другой Шаблон для архивов Рубрик. Иначе, WordPress будет исключать все записи в Рубрике 3, каждый раз, когда вы просматриваете Архив этой Рубрики!

Однако, если вы хотите использовать этот же файл шаблона, вы должны обойти это используя тэг is_home():

...
<?php if (in_category('3') && is_home() ) continue; ?>
...

Благодаря этому записи из Рубрики 3 будут исключены только с главной страницы. Существуют другие Условные Тэги, которые можно использовать для управления выводом в зависимости от того выполняется ли определенное условие на запрашиваемой странице.

Пожалуйста запомните, что несмотря на то что запись не отображается, WordPress все равно ее считает, как если бы она отображалась - это значит, что если вы указали WordPress выводить максимум семь записей, и две, последние из семи находятся в Рубрике 3, на главной странице отобразяться только пять записей. Если вы столкнулись с такой проблемой, можно воспользоваться более сложным приемом, описанным в разделе "Дизайн и Раскладка. Часто задаваемые вопросы" или вы можете использовать query_posts, если вам нужно просто исключить одну рубрику из Цикла.

Множественные Циклы

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

Во-первых, "зачем нужно использовать множественные Циклы?" Множественные циклы могут понадобиться в том случае, если вам необходимо произвести какие-то различные дейстия над несколькими группами записей, и при этом расположить их на одной странице. Различные действия - могут означать все что угодно, вы ограничены только PHP-мастерством и собственной фантазией.

Мы перейдем к примерам ниже, но сначала вы должны ознакомиться с основами. Взгляните на простой Цикл. Он состоит из:

     <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); ?>    
     <!-- атрибуты записи ... -->
     <?php endwhile; ?>

Проще говоря (люди, знакомые с 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 описывается, использование переменной для хранения результатов запроса. В примере 3 документирована функция update_post_caches();, используемая для обхождения общих проблем с плагинами. Наконец, "множественные циклы в действии" включает множество идей, одна из которых - использование множественных циклов для взаимодействия записей из конкретной категории на домашней странице вашего блога.

Множественные Циклы. Пример 1

Для того чтобы второй раз использовать цикл, с таким же запросом, вызовите функцию rewind_posts(). Она сбросит счетчик цикла и позволит вам выполнить другой цикл.

  <?php rewind_posts(); ?>
 
  <?php while (have_posts()) : the_post(); ?>
    <!-- получить записи... -->
  <?php endwhile; ?>

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

  // Получить последние 10 записей в рубрике special_cat
  <?php query_posts('category_name=special_cat&posts_per_page=10'); ?>

  <?php while (have_posts()) : the_post(); ?>
    <!-- получить записи из рубрики special_cat... -->
  <?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(); ?>
  <!-- получить записи из рубрики special_cat... -->
<?php endwhile; ?>

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

Множественные Циклы Пример 2

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

Например:

// оригинальный запрос сохраняется в переменную $temp_query
<?php $temp_query = $wp_query; ?>
<!-- Получить записи... -->

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

<?php while (have_posts()) : the_post(); ?>
  <!-- Получить записи из рубрики special_cat... -->
<?php endwhile; ?>

// $wp_query вновь присвается значение оригинального запроса
<?php $wp_query = $temp_query; ?>

Важно:В PHP5, оператор "=" создает ссылку на объект, вместо того что копировать его, как это было в php4. Чтобы Пример 2 заработал в PHP 5, вам нужно использовать следующий код:

 // оригинальный запрос сохраняется в переменную $temp_query
 <?php $temp_query = clone $wp_query; ?>
 <!-- Получить записи... -->
 
 <?php query_posts('category_name=special_cat&showposts=10'); ?>
 
 <?php while (have_posts()) : the_post(); ?>
   <!-- Получить записи из рубрики special_cat... -->
 <?php endwhile; ?>
 
 // $wp_query вновь присвается значение оригинального запроса
 <?php $wp_query = clone $temp_query; ?>

Однако, этот второй пример не работает в WordPress 2.1.

Множественные Циклы Пример 3 - Плагины

Было установлено, что некоторые плагины плохо взаимодействуют с множественными циклами. В этих случаях было обнаружено, что плагины, имеющие отношение к ключевым словам и тэгированию записей, работают только с первым циклом на странице, который включает в себя подмножество всех записей. Если вы столкнулись с подобным, можно попробовать следующую реализацию основного цикла, с добавлением функции update_post_caches($posts). Эта функция сбрасывает кэш записей, и пока не документирована. Эта реализация будет использоваться во втором цикле на странице, только если первый цикл вернул подмножество записей.

Просто замените следующие строки:

   <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); ?>    
     <!-- Получить записи... -->
   <?php endwhile; ?>

на эти:

   <?php if (have_posts()) : ?>
               <?php while (have_posts()) : the_post(); update_post_caches($posts); ?>
     <!-- Получить записи... -->
   <?php endwhile; ?>

Множественные Циклы в Действии

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

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

Шаг 1. Получить записи только из рубрики "featured".

  <?php $my_query = new WP_Query('category_name=featured&showposts=1');
  while ($my_query->have_posts()) : $my_query->the_post();
  $do_not_duplicate = $post->ID; ?>
    <!-- Получить записи... -->
  <?php endwhile; ?>

Говоря обычным языком, вышеуказанный код можно прочтитать так:

Установить $my_query равным результату запроса всех записей, где название рубрики featured, и кроме того, вернуть мне только одну запись. Также, установить значение переменной $do_not_duplicate равной ID-значению одиночной, возвращаемой записи. Выбрать то что описано в строке Получить записи вместе с параметрами форматирования, связанные с возвращаемой записью.

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

Шаг 2. Второй цикл, получение Х последних записей (исключая первую).

Представленный код получает X последних записей (как описано в настройках WordPress), сохраняет одну, уже отображенную в первом цикле, и отображает остальные записи, в соответствии с секцией Получить записи.

  <?php if (have_posts()) : while (have_posts()) : the_post(); 
  if( $post->ID == $do_not_duplicate ) continue; update_post_caches($posts); ?>
   <!-- Получить записи... -->
  <?php endwhile; endif; ?>

Говоря обычным языком, вышеуказанный код можно прочтитать так:

Получить все записи; где запись равна $do_not_duplicate, то ничего не делать (continue), в другом случае отобразить все другие записи в соответствии с секцией Do stuff. Также, обновить кэш, чтобы плагины связанные с тэгированием и ключевыми словами работали нормально. Вернуть переменную $do_not_duplicate, содержащую ID записи, ранее выведенной.

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

Here is what the final piece of code looks like without any formatting:

  <?php $my_query = new WP_Query('category_name=featured&showposts=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; update_post_caches($posts); ?>
   <!-- Do stuff... -->
  <?php endwhile; endif; ?>

В итоге мы получим два вывода. Первый вывод содержит самую свежую запись из категории 'featured'. Второй вывод будет содержать X свежих записей (Как задано в настройках Wordpress) за исключение записи которая уже показана в первом выводе. So, once the feature post is replaced with a new one, the previous feature will show up in standard post list section below (depending on how many posts you choose to display and on the post frequency). This technique (or similar) has been used by many in conjunction with knowledge of the Template Hierarchy to create a different look for home.php and index.php. See associated resources at the bottom of this page.

Note for Multiple Posts in the First Category

If showposts=2 or more, you will need to alter the code a bit. The variable $do_not_duplicate needs to be changed into an array as opposed to a single value. Otherwise, the first loop will finish and the variable $do_not_duplicate will equal only the id of the latest post. This will result in duplicated posts in the second loop. To fix the problem replace

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

with

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

Note that "showposts" can be any number. This changes $do_not_duplicate into an array. Then replace

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

with

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

Where you continue the pattern for whatever showposts is set equal to (2 in this case).

Sources

This article on multiple loops is a combination of Ryan Boren and Alex King's discussion about the Loop on the Hackers Mailing List as well as the tutorial written at MaxPower.

Дополнительные материалы