Изучаем WP_Query: Используем циклы

Как было отмечено во вступительной части этой серии статей, класс WP_Query состоит из четырех основных элементов:

  • Аргументы для запроса – о них мы поговорим более детально в следующих статьях из этой серии;
  • Сам запрос;
  • Цикл – выводит содержимое записи, заголовки или все то, что вам нужно вывести на экран;
  • Заключительная секция – здесь закрываются теги if и while, а также сбрасываются данные записи.

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

Где уместно использовать циклы

После того как WordPress запускает запрос с использованием указанных вами аргументов, ему нужно сообщить, что из извлеченных данных надо отобразить на странице. Именно здесь в действие вступает цикл.

При этом чаще всего используются три конструкции:

  • if($query->have_posts()) — проверяет наличие записей;
  • while($query->have_posts()) — повторяет цикл после каждой записи;
  • $query->the_post() — осуществляет доступ к конкретной записи.

Цикл в классе WP_Query выглядит следующим образом:

<?php

$args = array(
    // аргументы вашего запроса.
);

// произвольный запрос.
$query = new WP_Query( $args );

// проверка наличия результатов запроса.
if ( $query->have_posts() ) {

    // начало цикла обработки данных из результатов запроса.
    while ( $query->have_posts() ) {

        $query->the_post();

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

    }

}

// Восстановление исходных данных записи.
wp_reset_postdata();

?>

Структура цикла

Структура вашего цикла, зависит от того, какие данные из записи вы хотите вывести на экран. Предлагаем вам пример цикла, который выводит заголовок записи, миниатюру и отрывок из текста:

<?php

$args = array(
    // аргументы вашего запроса.
);

// произвольный запрос.
$query = new WP_Query( $args );

// проверка наличия результатов запроса.
if ( $query->have_posts() ) {

    // начало цикла обработки данных из результатов запроса.
    while ( $query->have_posts() ) {

        $query->the_post();

        ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php post_thumbnail( 'thumbnail' );?>
            </a>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php the_title(); ?>
            </a>
            <?php the_excerpt(); ?>
        </article>

        <?php

    }

}

// Восстановление исходных данных записи.
wp_reset_postdata();

?>

Проверка содержимого с помощью циклов

Иногда перед списком записей нужно вывести заголовок, или же поместить все записи в отдельный элемент. Если вы добавите необходимые теги перед циклом, то они будут просто выводиться на странице без возврата данных. То есть выведется лишь один заголовок или вся разметка.

Эту проблему легко обойти, если поместить элемент или заголовок внутрь самого тега:

<?php

$args = array(
    // аргументы вашего запроса
);

// произвольный запрос.
$query = new WP_Query( $args );

// проверка наличия результатов запроса
if ( $query->have_posts() ) {

    echo '<section class="clear">';
        echo '<h2>' . __( 'Heading', 'tutsplus' ) . '</h2>';

        // начало цикла обработки данных из результатов запроса
        while ( $query->have_posts() ) {

            $query->the_post();

            ?>

            <article id="post-<?php the_ID(); ?>" <?php post_class( 'left' ); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php post_thumbnail( 'thumbnail' );?>
                </a>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
                <?php the_excerpt(); ?>
            </article>

            <?php

        }

    echo '</section>';

}

// восстановление исходных данных записи.
wp_reset_postdata();

?>

Сначала мы проверяем, вернул ли наш запрос какие-нибудь записи. Если да, то мы открываем содержащий их элемент и добавляем в него заголовок. Давайте предположим, что нам нужно создать список со всеми записями из определенной рубрики.

Элемент списка ul находится за пределами нашего цикла, так как не связан с какой-то определенной записью, и нам нужно выводить его только при наличии записей:

<?php

$args = array(
    'category_name' => 'category-slug',
    'post_type' => 'post'
);

// произвольный запрос.
$query = new WP_Query( $args );

// проверка наличия результатов запроса.
if ( $query->have_posts() ) {

    echo '<ul class="category posts">';

        // начало цикла обработки данных из результатов запроса.
        while ( $query->have_posts() ) {

            $query->the_post();

            ?>

            <li <?php post_class( 'left' ); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
            </li>

            <?php

        }

    echo '</ul>';

}

// восстановление исходных данных записи.
wp_reset_postdata();

?>

Мы проверяем, извлек ли запрос какие-нибудь записи, и если да, то мы открываем ul-элемент, а затем запускаем цикл.

Запуск дополнительных циклов

jQuery можно использовать для запуска нескольких циклов, но для этого нужно восстанавливать данные записи после каждого цикла, и только потом запускать второй экземпляр класса WP_Query. Потому что каждый цикл будет возвращать данные на основе заданных ему значений аргументов.

В этом примере выводится отрывок текста и миниатюра из первой записи, а затем заголовки каждой последующей записи:

<?php

// аргументы первого запроса.
$args1 = array(
    'post_type' => 'post',
    'posts_per_page' => '1'
);

// первый произвольный запрос.
$query1 = new WP_Query( $args1 );

// проверка наличия результатов запроса.
if ( $query1->have_posts() ) {

    // начало цикла обработки данных из результатов запроса.
    while ( $query1->have_posts() ) {

        $query1->the_post();

        ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php post_thumbnail( 'thumbnail' );?>
            </a>
            <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                <?php the_title(); ?>
            </a>
            <?php the_excerpt(); ?>
        </article>

        <?php

    }

}

// восстановление исходных данных записи.
wp_reset_postdata();

// аргументы второго запроса.
$args2 = array(
    'offset' => '1',
    'post_type' => 'post'
);

// второй произвольный запрос.
$query2 = new WP_Query( $args2 );

// проверка наличия результатов запроса.
if ( $query2->have_posts() ) {

    echo '<ul class="more-posts">';

        // начало цикла обработки данных из результатов запроса.
        while ( $query2->have_posts() ) {

            $query2->the_post();

            ?>

            <li <?php post_class(); ?>>
                <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>">
                    <?php the_title(); ?>
                </a>
            </li>

            <?php

        }

    echo '</ul>';

}

// восстановление исходных данных записи.
wp_reset_postdata();

?>

Здесь мы использовали два ключевых аргумента:

  • posts_per_page’ => ‘1’, используется в первом запросе для вывода последней записи;
  • ‘offset’ = ‘1’, используется во втором запросе, пропускает самую свежую запись, чтобы избежать ее повторения в создаваемом списке.

Как видно из примера, цикл лишь слегка отличается для каждого запроса. Первый запрос выводит миниатюру, заголовок и выдержку из самой свежей записи, а второй запрос проверяет наличие записей в запросе. Если они есть, то открывает ul-элемент и включает в него заголовок каждой записи, обрамленный в элемент li с указанием ссылки на страницу записи.

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

В завершение

Цикл – это код, который вы используете для вывода данных, которые WordPress извлек из базы данных, руководствуясь аргументами вашего запроса.

Простой цикл выводит все записи в порядке, указанном в аргументах запроса (либо по дате по умолчанию). Если вы разделите if( $query->have_posts() ) и while( $query->have_posts() ), то сможете использовать дополнительную разметку прямо внутри цикла, но только, если запрос вернул какие-либо данные. И, наконец, указывая альтернативные аргументы и используя функцию wp_reset_postdata() после каждого цикла, вы можете применять WP_Query несколько раз в рамках отдельной страницы.

Перевод статьи “Mastering WP_Query: Using the Loop” был подготовлен дружной командой проекта Сайтостроение от А до Я.