Статьи

Как кодировать несколько циклов, выполняя только один запрос к базе данных

Я большой поклонник класса WP_Query : я использую его на многих своих клиентских сайтах для запроса и вывода контента нестандартными способами.

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

Итак, здесь я покажу вам, как использовать один запрос для выполнения более одного цикла. Вы можете сделать это с помощью основного запроса (что я и сделаю, так как он более эффективен) или использовать ту же технику с WP_Query .

Есть три части к этому:

  • Создайте дочернюю тему и файл шаблона.
  • Создайте шаблонную часть для содержимого цикла.
  • Создайте наши петли.

Итак, начнем!

Чтобы следовать, вам нужно:

  • Разрабатываемая установка WordPress.
  • Редактор кода.
  • Сообщения на вашем сайте с несколькими назначенными категориями — я использую данные модульного теста темы WordPress .
  • Двадцать шестнадцать тем, установленных на вашем сайте.
  • Установлена ​​и активирована дочерняя тема из двадцати шестнадцати — здесь я кратко расскажу о настройке дочерней темы.

Вам не нужно использовать двадцать шестнадцать с дочерней темой — вы можете адаптировать эту технику для своей собственной темы. Но я буду использовать ребенка двадцати шестнадцати лет.

Сначала давайте создадим детскую тему двадцати шестнадцати. Я делаю это, потому что я не хочу редактировать саму тему.

В каталоге wp-content/themes создайте новую пустую папку. Я звоню в мой tutsplus-one-query-two-loops .

В этой папке создайте файл с именем style.css и добавьте в него:

01
02
03
04
05
06
07
08
09
10
11
/*
Theme Name: Tutsplus One Query Multiple Loops
Theme URI: http://.tutsplus.com/tutorials/how-to-code-multiple-loops-while-only-querying-the-database-once—cms-25703
Description: Theme to support Tutorial on running multiple loops while querying the database just once.
Author: Rachel McCollin
Author URI: http://rachelmccollin.co.uk/
Template: twentysixteen
Version: 1.0
*/
 
@import url(«../twentysixteen/style.css»);

Теперь сохраните этот файл и активируйте новую тему.

Следующим шагом будет создание файла шаблона для категорий, с которым мы будем работать.

Сделайте копию файла archive.php из двадцати шестнадцати в вашей новой теме. Не двигайте это, но скопируйте это. Переименуйте его в category.php . Теперь это файл шаблона для категорий на вашем сайте.

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

В папке вашей темы создайте подпапку с названием includes . Внутри этого создайте новый файл с именем loop-category.php .

Теперь откройте файл template-parts/content.php из файла двадцати шестнадцати и найдите этот код (который составляет большую часть файла):

01
02
03
04
05
06
07
08
09
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
39
40
41
42
43
44
45
46
47
<article id=»post-<?php the_ID(); ?>» <?php post_class();
    <header class=»entry-header»>
        <?php if ( is_sticky() && is_home() && ! is_paged() ) : ?>
            <span class=»sticky-post»><?php _e( ‘Featured’, ‘twentysixteen’ );
        <?php endif;
 
        <?php the_title( sprintf( ‘<h2 class=»entry-title»><a href=»%s» rel=»bookmark»>’, esc_url( get_permalink() ) ), ‘</a></h2>’ );
    </header><!— .entry-header —>
 
    <?php twentysixteen_excerpt();
 
    <?php twentysixteen_post_thumbnail();
 
    <div class=»entry-content»>
        <?php
            /* translators: %s: Name of current post */
            the_content( sprintf(
                __( ‘Continue reading<span class=»screen-reader-text»> «%s»
                get_the_title()
            ) );
 
            wp_link_pages( array(
                ‘before’ => ‘<div class=»page-links»><span class=»page-links-title»>’ .
                ‘after’ => ‘</div>’,
                ‘link_before’ => ‘<span>’,
                ‘link_after’ => ‘
                ‘pagelink’ => ‘<span class=»screen-reader-text»>’ .
                ‘separator’ => ‘<span class=»screen-reader-text»>,
            ) );
        ?>
    </div><!— .entry-content —>
 
    <footer class=»entry-footer»>
        <?php twentysixteen_entry_meta();
        <?php
            edit_post_link(
                sprintf(
                    /* translators: %s: Name of current post */
                    __( ‘Edit<span class=»screen-reader-text»> «%s»
                    get_the_title()
                ),
                ‘<span class=»edit-link»>’,
                ‘
            );
        ?>
    </footer><!— .entry-footer —>
</article><!— #post-## —>

Скопируйте это в ваш новый файл.

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

В вашем новом файле loop-category.php найдите этот код и удалите его:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<div class=»entry-content»>
    <?php
        /* translators: %s: Name of current post */
        the_content( sprintf(
            __( ‘Continue reading<span class=»screen-reader-text»> «%s»
            get_the_title()
        ) );
 
        wp_link_pages( array(
            ‘before’ => ‘<div class=»page-links»><span class=»page-links-title»>’ .
            ‘after’ => ‘</div>’,
            ‘link_before’ => ‘<span>’,
            ‘link_after’ => ‘
            ‘pagelink’ => ‘<span class=»screen-reader-text»>’ .
            ‘separator’ => ‘<span class=»screen-reader-text»>,
        ) );
    ?>
</div><!— .entry-content —>

Другим шагом является замена функции twenty_sixteen_excerpt() на стандартную the_excerpt() , поскольку в версии двадцати шестнадцати нет ссылки на полный пост.

Найдите эту строку:

1
<?php twenty_sixteen_excerpt();

Замените это на это:

1
<?php the_excerpt();

Нам также нужно сделать несколько настроек тегов заголовка.

В части шаблона отредактируйте строку:

1
<?php the_title( sprintf( ‘<h2 class=»entry-title»><a href=»%s» rel=»bookmark»>’, esc_url( get_permalink() ) ), ‘</a></h2>’ );

Измените теги h2 на h3 :

1
<?php the_title( sprintf( ‘<h3 class=»entry-title»><a href=»%s» rel=»bookmark»>’, esc_url( get_permalink() ) ), ‘</a></h3>’ );

Сохраните свой файл детали шаблона. Теперь вернитесь к файлу category.php и продолжайте работать в этом.

Сначала давайте удалим вызов двадцать шестнадцатой части шаблона из нашего файла category.php, так как вместо этого нам нужно будет использовать новый файл.

В вашем файле category.php найдите этот код:

1
get_template_part( ‘template-parts/content’, get_post_format() );

Удалить это.

Теперь мы создадим петли.

В этом примере я сначала перечислю все сообщения с тегом «content», используя условный тег has_tag() .

Это означает, что мне придется запустить три цикла:

  • Первый проверяет, вернул ли запрос какие-либо сообщения с этим тегом.
  • Если это так, второй выводит сообщения с этим тегом.
  • Третий выводит посты без этого тега.

Между каждым из них я буду использовать rewind_posts() чтобы перематывать сообщения без сброса запроса: мы все еще работаем с основным запросом каждый раз.

В вашем файле category.php найдите начало цикла:

1
while ( have_posts() ) : the_post();

Над этой строкой определите новую переменную с именем $count :

1
$count = 0;

Теперь внутри этого цикла, добавьте этот код:

1
2
3
4
5
// check if there are any posts with the » tag
$tag = ‘content’;
if ( has_tag( $tag ) ) {
    $count +=1;
}

Это проверяет, есть ли у постов тег ‘content’, а затем добавляет 1 к количеству, если так.

Ваш цикл теперь будет выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
// Check for posts in the first loop.
$count = 0;
while ( have_posts() ) : the_post();
 
// check if there are any posts with the » tag
$tag = ‘content’;
if ( has_tag( $tag ) ) {
    $count +=1;
}
     
endwhile;

Следующий шаг — запустить цикл для вывода сообщений с этим тегом, но только если они есть, т. Е. Если значение $count больше 0 .

Добавьте это ниже вашего первого цикла:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
if ( $count > 0 ) {
                     
    rewind_posts();
 
    echo ‘<h2>Posts tagged with ‘ .
 
     
    while ( have_posts() ) : the_post();
     
    if ( has_tag( $tag ) ) {
        get_template_part( ‘includes/loop’, ‘category’);
    }
     
    // End the loop.
    endwhile;
     
}

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

Финальный цикл выведет остальные сообщения. Если в этой категории нет сообщений с тегом «content», то будут выведены все сообщения в категории.

Ниже вашего второго цикла добавьте это:

01
02
03
04
05
06
07
08
09
10
11
12
rewind_posts();
         
 
// Second Loop — posts not with the ‘content’ tag
while ( have_posts() ) : the_post();
         
    if ( !has_tag( $tag ) ) {
        get_template_part( ‘includes/loop’, ‘category’);
    }
         
// End the loop.
endwhile;

Это перематывает посты (что вы будете делать в первый раз, если не было постов с тегом, или второй раз, если они были), а затем снова запускает цикл. На этот раз он проверяет , не имеет ли пост тег ‘content’, и выводит его, используя нашу часть шаблона.

Теперь проверьте страницу архива категорий на вашем сайте.

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

Страница категории с двумя циклами

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

Важное примечание: не query_posts() искушению использовать query_posts() для изменения основного запроса, когда вы делаете это. Это замедлит ваш сайт больше, чем если бы вы использовали несколько запросов.

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