10 полезных приемов по работе с циклом Loop в WordPress

10 полезных приемов по работе с циклом Loop в WordPress
Цикл Loop — крайне важная составляющая блогов WordPress. Именно он отвечает за получение записей из базы данных WordPress с выводом их на экран. Возможности этого инструмента с полезными и удобными опциями крайне широки: можно запросить одну запись, список записей, упорядоченных по дате, названию или категориям, список записей конкретного автора и пр.
В этой статье мы рассмотрим 10 полезных функций реализованного в WordPress цикла loop, которые, надеемся, дополнительно расширят возможности вашего блога.

1. Выборка записей в промежутке времени

Выборка записей в промежутке времени
Проблема. Скомбинировав в WordPress цикл loop с функцией "query_posts()", можно легко получить список записей, опубликованных за конкретную неделю или месяц. А вот если нужны записи, предположим, с 17 марта по 3 мая, задача усложняется.

Решение. Добавьте приведенный ниже код туда, где в теме планируется отображать выборку записей между двумя датами (не забудьте заменить даты из примера своими):

<?php
function filter_where($where = '') {
$where .= " AND post_date >= '2009-03-17' AND post_date <= '2009-05-03'";
return $where;
}
add_filter('posts_where', 'filter_where');
query_posts($query_string);
while (have_posts()) :
the_post();
the_content();
endwhile;
?>

Анализ кода. Чтобы добиться нужного результата, сначала я создаю функцию "filter_where()" с SQL-условием "WHERE". После, непосредственно перед началом loop'а, функция "filter_where()" привязывается к еще одной функции WordPress — "post_where()".
В результате содержащийся в функции "filter_where()" оператор "WHERE" добавляется в конец SQL-запроса из функции "post_where()". Это означает, что loop будет возвращать записи, опубликованные исключительно в период между заданными в функции "filter_where()" датами.

2. Использование нескольких loop'ов на странице, без дублирования записей

Использование нескольких loop'ов на странице, без дублирования записей
Проблема. В большинстве актуальных тем и во всех "журнальных" на домашней странице блога отображается как минимум два loop'а, например, для раздела "Популярные записи". Совместить два loop'а просто, а вот предотвратить дублирование в них записей уже сложнее... если не знать простого способа сделать это.

Решение.
1. Начнем с первого loop'а. Здесь ничего проблематичного: получаем восемь опубликованных последними записей с помощью параметра "showposts". Откройте файл "index.php" и добавьте в него следующий код, который будет отвечать за вывод "популярных" записей:

<?php
query_posts('showposts=8');
$ids = array();
while (have_posts()) : the_post();
$ids[] = get_the_ID();
the_title();
the_content();
endwhile;
?>

2. Теперь применим второй loop для выбора всех записей за исключением выведенных первым loop.

<?php
query_posts(array('post__not_in' => $ids));
while (have_posts()) : the_post();
the_title();
the_content();
endwhile;
?>

3. Сохраняем файл "index.php" и наслаждаемся результатом.

Анализ кода. Первый loop начинается с крайне полезной функции "query_posts()", позволяющей задавать для него самые разные параметры. Параметр "showposts" служит для выборки определенного количества записей. Непосредственно перед запуском loop'а создаю PHP массив с именем "$ids", который будет получать все идентификаторы всех возвращаемых loop'ом записей .
Второй loop, как и первый, использует функцию "query_posts()" с параметром "post__not_in", определяющим список нежелательных для вывода записей в форме PHP массива. Как вы, наверное, заметили, этому параметру я передал массив "$ids", чтобы все возвращенные первым loop'ом записи снова возвращались вторым loop'ом.

3. Вставка рекламы после первой записи

Вставка рекламы после первой записи
Проблема. Реклама — верный способ сделать блог доходным. Но рекламодатели приходят только тогда, когда посетители начинают щелкать по объявлениям. Многие блоггеры добавляют рекламу сбоку, внизу или вверху страницы — прямо скажем, не на лучшие места для эффективных баннеров. Почему бы не вставить рекламу после первой записи? Получим больше кликов — и довольных рекламодателей. Посмотрим, как решить эту задачу в WordPress с помощью loop'а.

Решение. Просто замените текущий loop представленным ниже (не забудьте в строке 6 указать собственный код рекламы):

<?php if (have_posts()) : ?>
<?php $count = 0; ?>
<?php while (have_posts()) : the_post(); ?>
<?php $count++; ?>
<?php if ($count == 2) : ?>
//Paste your ad code here
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
<?php else : ?>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
<?php endif; ?>
<?php endwhile; ?>
<?php endif; ?>

Анализ кода. Еще на заре программирования в качестве счетчиков было принято использовать целочисленные переменные. Именно так мы здесь и поступим: непосредственно перед началом loop'а создается переменная "$count". Для каждого возвращаемого циклом результата она увеличивается на единицу.
Теперь достаточно добавить структуру "if" (строка 5) и проверить, равна ли переменная "$count" двум. Если да, значит, первая запись уже возвращена, и можно выводить рекламу.

4. Выбор записи по дополнительному полю и значению

Выбор записи по дополнительному полю и значению
Проблема. Поскольку дополнительные поля в WordPress неизменно пользуются популярностью, зачастую возникает потребность в выводе списка записей с определенными дополнительными полями и значениями. Для опытных пользователей WordPress здесь все просто, а вот новички постоянно задают мне этот вопрос в блогах. Вот как правильно и быстро это сделать.

Решение. Ничего сложного. Нам понадобится лишь функция "query_posts()" с параметрами "meta_key" и "meta_value":

<?php query_posts('meta_key=review_type&meta_value=movie');  ?>
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>

Анализ кода. В принципе, все ясно. Чтобы выбрать записи с определенными дополнительными полями и значениями, воспользуйтесь функцией "query_posts()" с параметрами "meta_key" и "meta_value". Величина "meta_key" — имя нужного дополнительного поля, а "meta_value", соответственно, — значения.

5. Список "будущих" записей

Список "будущих" записей
Проблема. Благодаря опции планирования записей "schedule post" в любимых блогах можно, создавая записи, откладывать их публикацию на более поздний срок. Чтобы читателям захотелось вернуться или подписаться на RSS-ленту, неплохо было бы опубликовать список планируемых записей.

Решение.

<?php query_posts('showposts=10&post_status=future'); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<h2><?php the_title(); ?></h2>
<span class="datetime"><?php the_time('j. F Y'); ?></span></p>
<?php endwhile;
else: ?><p>No future events scheduled.</p>
<?php endif; ?>

Анализ кода. Для этой цели я воспользовался функцией "query_posts()" с интересным параметром "post_status". С его помощью можно выбирать записи по состоянию публикации ("опубликована", "черновик" или, как в нашем примере, "запланирована"). Поскольку я добавил еще и параметр "showposts=10", код будет возвращать не более 10 запланированных записей.

6. Отображение записи опубликованной год назад

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

Решение. Если блог ведется относительно давно, почему бы не отображать записи, которым уже больше года? Сделать это просто: вставьте представленный ниже код в боковой блок или в файл "single.php".

<?php
$current_day = date('j');
$last_year = date('Y')-1;
query_posts('day='.$current_day.'&year='.$last_year);
if (have_posts()):
while (have_posts()) : the_post();
the_title();
the_excerpt();
endwhile;
endif;
?>

Анализ кода. Сначала нужно было получить текущую дату, что мы и сделали в строке 2 с помощью PHP функции "date()". После этого нам понадобилась прошлогодняя дата, которую легко получить вычитанием единицы из возвращаемого "date('Y')" результата.
После этого останется передать переменные "$current_day" и "$last_year" параметрам "day" и "year" функции "query_posts WordPress".
Кстати, если по какой-либо причине решите выводить только сегодняшние записи, удалите строку 3, а четвертую замените на:

query_posts('day='.$current_day);

7. Использование loop'а для создания интересной страницы Архива

Использование loop'а для создания интересной страницы Архива
Проблема. Как уже отмечалась выше, общая проблема блогов — в затрудненном доступе к старой информации.
Чтобы помочь моим читателям в поисках, я создал шаблон страницы WordPress с полным списком опубликованных в блоге записей - (http://www.wprecipes.com/archives).

Решение. Тем, кто не знает, что такое шаблон страницы и как работать с ним в блоге, рекомендую начать с этой небольшой заметки http://www.wprecipes.com/how-to-create-and-use-wordpress-page-templates (на англ. языке).

<?php
/*
Template Name: Archives
*/
?>

<?php get_header(); ?>

<h2><?php $numposts = $wpdb->get_var("SELECT COUNT(*) FROM $wpdb->posts WHERE post_status = 'publish'");
if (0 < $numposts) $numposts = number_format($numposts); ?>
<h2><?php echo $numposts.' recipes published since October 06, 2008'; ?></h2>

<ul id="archive-list">
<?php
$myposts = get_posts('numberposts=-1&');
foreach($myposts as $post) : ?>
<li><?php the_time('m/d/y') ?>: <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; ?>
</ul>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Анализ кода. Для начала создадим "шаблон страницы", добавив в верхнюю часть файла следующие строки:

<?php
/*
Template Name: Archives
*/
?>

Обратите внимание на счетчик записей (строка 8). Принцип его работы основан на создании PHP переменной с именем "$numposts" и использовании объекта "$wpdb" для получения результата SQL запроса, направленного базе данных WordPress.
Теперь нам осталось лишь отобразить переменную "$numposts" — на экран будет выведено общее количество записей в блоге.
Немного подробнее о цикле loop в данном коде. Как вы уже, вероятно, заметили, вместо классического loop'а здесь задействована функция "get_posts()" — простой тег для создания множественных loop'ов. Получаем от программы все записи и для каждой из них выводим дату, ссылку и название. Просто и эффективно.

8. Создание своих loop'ов при помощи объекта WP_Query

Создание своих loop'ов при помощи объекта WP_Query
Проблема. Классический цикл loop в WordPress, о котором здесь идёт речь практически в каждом приеме, удобен и прост в работе. Однако при большом количестве пользовательских loop'ов (в частности, в сложных "журнальных" макетах) появляются проблемы со сбросом, смещением, некорректными тегами условий и прочие мелкие неприятности.

Решение. Воспользуйтесь объектом "WP_Query" для создания своего собственного loop'а.

<?php
$myPosts = new WP_Query();
$myPosts->query('showposts=5');

while ($myPosts->have_posts()) : $myPosts->the_post(); ?>
the_title();
the_content();
endwhile;
?>

Анализ кода. Представленный выше код выводит на экран пять опубликованных последними записей. Вот как это происходит:
* в строке 2 я создал новый объект "WP_Query" с именем "$myPosts";
* в строке 3 отправил запрос с помощью параметра "showposts" на получение пяти опубликованных последними записей;
* в строке 5 начинается собственный loop;
* в строках 6 и 7 мы публикуем базовую информацию по записи (название, содержание);
* в строке 8 собственный loop завершается.
Чтобы отобразить больше или меньше записей, достаточно отредактировать значение параметра "showposts" в строке 3.

9. Выбор в loop'е только "приклеенных" записей

Выбор в loop'е только "приклеенных" записей
Проблема. Появившиеся в WordPress 2.7 "приклеенные" записи — отличная опция любимой блог-платформы. Многие пользователи WordPress интересуются, как выбрать в loop'е только "приклеенные" записи.

Решение. Для отображения пяти опубликованных последними "приклеенных" записей вставьте приведенный ниже код в любой из файлов темы. Чтобы записей отображалось больше или меньше, в строке 4 замените число 5 нужным значением.

<?php
$sticky = get_option('sticky_posts');
rsort( $sticky );
$sticky = array_slice( $sticky, 0, 5);
query_posts( array( 'post__in' => $sticky, 'caller_get_posts' => 1 ) );

if (have_posts()) :
while (have_posts()) : the_post();
the_title();
the_excerpt();
endwhile;
endif;
?>

Анализ кода. Первым делом выбрали все "приклеенные" записи (строка 2). После изменили их порядок, собирав сверху опубликованные последними с помощью PHP функции "rsort()" (строка 3). В строке 4 мы выбрали пять последних "приклеенных" записей. Как уже упоминалось выше, их количество можно произвольно менять.
После этого устанавливаем контроль за loop'ом посредством функции "query_posts()". Параметр "post__in" гарантирует, что полученные записи попадают в массив значений, который и является переменной "$sticky". Теперь настраиваем базовый loop и выводим нужную информацию на экран.

10. Создание loop'а из изображений

Создание loop'а из изображений
Проблема. В основной части блогов цитаты из записей вместе с изображениями размещены на домашней странице. А что если выбрать подход оригинальнее и представить читателям симпатичную страницу-"галерею" с любым количеством опубликованных последними записей и открывающими их изображениями? Само собой, сделать это можно и с помощью дополнительных полей, но, верьте или нет, они совершенно необязательны.

Решение. Для создания loop'а из изображений нам потребуется PHP функция, получающая первое изображение из каждой записи и возвращающая его URL-адрес. Для этого в файл "functions.php" добавьте представленную ниже функцию (в строке 10 не забудьте указать изображение по умолчанию).

function catch_that_image() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
$first_img = $matches [1] [0];

if(empty($first_img)){ //Defines a default image
$first_img = "/images/default.jpg";
}
return $first_img;
}

После сохранения файла "functions.php" можно отображать loop из изображений:

<?php
if (have_posts()) :
while (have_posts()) : the_post(); ?>
<a href="<?php the_permalink();?>" title="<?php the_title(); ?>" class="img-loop">
<img src="http://media2.smashingmagazine.com/wp-content/uploads/images/wordpress-loop-hacks/<?php echo catch_that_image() ?>" alt="<?php the_title(); ?>" />
</a>
endwhile;
endif;
?>

Анализ кода. Первая часть кода представляет собой добавленную в файл "functions.php" функцию "catch_that_image()". Данная функция анализирует содержимое записи с помощью глобальных переменных "$post" и "$posts", а также регулярного PHP выражения. Если изображения не обнаружено (т.е. в записи его нет), возвращается заданный по умолчанию URL-адрес. В ином случае — URL-адрес первого изображения записи.
Вторая часть кода является собственно loop'ом и не представляет собой ничего сложного — базовый loop без текстового наполнения. Вместо него функция "catch_that_image()" выводит первое изображение записи.

Мой перевод статьи 10 Useful WordPress Loop Hacks

Рубрика: Настройка WordPress | 18 июня 2009

Предыдущие записи из рубрики `Настройка WordPress`

17 комментариев

delphix, 21.06.2009 в 15:09

Отличный пост, большое спасибо за работу, но

1. пробовал вывести прошлогодние записи в сайд баре -получил ошибку типа T_variable expected ....

и вопрос попутно как можно его модифицировать (цикл) чтобы не прошлый год показывался а к примеру этот день в прошлом месяце или прошлая неделя

ОтветитьОтветить
Deimos, 21.06.2009 в 19:11

delphix, не за что! На счет ошибки завтра с утра проверю и отпишусь!

ОтветитьОтветить
Юрий, 23.06.2009 в 13:59

Спасибо за очень интересный блог: прочел всего три стаьи - и уже узнал для себя очень много нового. По поводу пункта 9. Подскажите, пожалуйста, как сделать, чтобы приклееный сверху пост не появлялся в главной ленте, пока я его не "отклею"?

ОтветитьОтветить
Deimos, 23.06.2009 в 14:03

Юрий, не совсем Вас понимаю 🙁 Всмысле не появлялся в главной ленте пока вы его не "отклеете"? В RSS ленте имеете в виду или на главной странице?

ОтветитьОтветить
Юрий, 23.06.2009 в 16:36

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

ОтветитьОтветить
Deimos, 24.06.2009 в 08:02

Сегодня ближе к вечеру разберусь как сделать и отпишу Вам на почту!

ОтветитьОтветить
Алексей, 10.07.2009 в 16:07

Решил попробовать использовать функцию "catch_that_image()" для вывода картинок к записям на главной и в категориях. Неожиданно возникла такая проблема:
На локальном компе все получается, как сайт перенес на хостинг, картинки не выводятся. Ни загруженные через атачмент, ни дефолтная. На всякий случай всему чему можно присвоил 777, посмотрел в исходнике - путь указан верно <img src="http://site.ru/wp-content/themes/Pemuda/thumb.php?src=http://site.ru/images/default.jpg&h=130&w=150&zc=1&q=100" class="theimage" /] (напрямую выводятся).
Дмитрий, SOS, подскажите пожалуйста, где меня сглазили. Край как нужно!

ОтветитьОтветить
Алексей, 10.07.2009 в 18:04

Немного уточню ссылка [http://site.ru/images/default.jpg] выводит картинку, а полная [http://site.ru/wp-content/themes/Pemuda/thumb.php?src=http://site.ru/images/default.jpg] не хочет.
Это что проблема в файле thumb.php?

ОтветитьОтветить
Алексей, 10.07.2009 в 20:02

Мои извинения.
Проблема оказалась не в Вордпрессе.
Закинул эту же тему на другой хостинг - все работает, при условии что выставляю 777 для папки "cache" - есть такая внутри темы. На прежнем хостере тоже даю такие же права - ни каких изменений.
Может быть подскажете, как постороить разговор с хостером, в плане что подключить и тд.
Спасибо

ОтветитьОтветить
Deimos, 10.07.2009 в 20:12

Алексей, добрый вечер, можете кинуть сюда или на почту (через обратную связь) ссылку на Вашу тему, надо взглянуть что там в thumb.php... Может просто расширение для php какое нибудь не стоит....

ОтветитьОтветить
Алексей, 10.07.2009 в 20:17

http://www.wpcredo.ru/?p=978

ОтветитьОтветить
Алексей, 10.07.2009 в 20:28

Блин так обидно, что полдня убил на такой пустяк.
Пришло от хостера:
"бла-бла-бла. Обычно вообще не возникает необходимости менять права доступа на файлы или папки при установке скриптов. Пожалуйста, помните - нельзя устанавливать права доступа 777 или 666, иначе сервер будет блокировать скрипт."
Все получилось. Еще раз спасибо

ОтветитьОтветить
Deimos, 11.07.2009 в 11:45

Алексей, ну ведь хорошо, что само все решилось, еще пол дня не надо тратить на исправление косяка - если бы он был 😉

ОтветитьОтветить
alexpts, 19.08.2010 в 22:51

А как вывести число вложенных атачментов у поста не знаешь?

ОтветитьОтветить
Денис, 15.05.2011 в 13:42

Сасибо за полезную подборку! Мне очень помог пример про прилепленные записи, не знал как делать 🙂

ОтветитьОтветить
ChDamir, 27.05.2011 в 11:28

Добавочка по пункту "2. Использование нескольких loop'ов на странице, без дублирования записей".

В кодексе есть перевод на тему 2-х циклов. Меня выручил раздел "Конечный результат" в самом низу. Надо было первую запись выделить. Обычным if'ом и счетчиком не получалось. Точнее 1-я страница ок, а дальше кривота была. Не помогали rewind_posts() и wp_reset_query(). А update_post_caches($posts) помог.

ОтветитьОтветить
Аркадий, 23.06.2013 в 14:07

Добрый день подскажите пожалста, как реализовать на сайте выборку записей, на сегодня, на завтра, на неделю, на месяц, то есть у меня записи-это мероприятия, я добавляю мероприятия на какой-то день, и пользователь при нажатии "на завтра" к примеру должен получить мероприятия на завтра, при этом даты мероприятий я выставляю сам?

ОтветитьОтветить

Комментировать