Некоторые сомнения по поводу того, как основной запрос и пользовательский запрос работает в этой пользовательской теме?

20

Я довольно новичок в разработке тем WordPress и не очень разбираюсь в PHP (я пришел с Java и C #), и у меня есть следующая ситуация в этой пользовательской теме

Как вы можете видеть на главной странице, я сначала показываю раздел (названный Articoli в evidenza ), содержащий избранные посты (я реализовал его с помощью определенного тега), а под ним есть еще одна область (названная Ultimi Articoli ), которая содержит последнее сообщение. это не показанный пост.

Для этого я использую этот код:

<section id="blog-posts">

<header class="header-sezione">
        <h2>Articoli in evidenza</h2>
</header>

<!--<?php query_posts('tag=featured');?>-->

<?php
    $featured = new WP_Query('tag=featured');

    if ($featured->have_posts()) : 
            while ($featured->have_posts()) : $featured->the_post();
            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
                 get_template_part('content', get_post_format());

             endwhile;
        wp_reset_postdata();
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>


<header class="header-sezione">
    <h2>Ultimi Articoli</h2>
</header>

<?php
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            /*
             * Include the post format-specific template for the content. If you want to
             * use this in a child theme, then include a file called called content-___.php
             * (where ___ is the post format) and that will be used instead.
             */
            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
    ?>

</section>

Он работает нормально, но у меня есть некоторые сомнения по поводу качества этого решения и как именно оно работает.

Чтобы выбрать все избранные сообщения , я использую эту строку, которая создает новый WP_Queryобъект, который определяет запрос, имеющий определенный тег featured:

$featured = new WP_Query('tag=featured');

Затем я повторяю этот результат запроса, используя его have_posts()метод.

Итак, насколько я понимаю, это не основной запрос WordPress, а новый запрос, созданный мной. Из того, что я понимаю, лучше создать новый запрос (как сделано) и не использовать основной запрос, когда я хочу выполнить этот вид операции.

Это правда или я что-то упустил? Если это правда, можете ли вы объяснить мне, почему лучше создать новый пользовательский запрос, а не изменять основной запрос Wordpress?

Хорошо, продолжай. Я показываю все сообщения, у которых нет тега «Featured». Для этого я использую этот фрагмент кода, который, напротив, изменяет основной запрос:

    <?php
    // get the term using the slug and the tag taxonomy
    $term = get_term_by( 'slug', 'featured', 'post_tag' );
    // pass the term_id to tag__not_in
    query_posts( array( 'tag__not_in' => array ( $term->term_id )));
    ?>

    <?php
        if (have_posts()) :
            // Start the Loop.
            while (have_posts()) : the_post();
                get_template_part('content', get_post_format());

            endwhile;
        else :
            // If no content, include the "No posts found" template.
            get_template_part('content', 'none');

        endif;
        ?>

Так что я думаю, это довольно ужасно. Это правда?

ОБНОВИТЬ:

Для выполнения той же операции я нашел эту функцию (в отличном ответе ниже), которую я добавил в functions.php

function exclude_featured_tag( $query ) {
    if ( $query->is_home() && $query->is_main_query() ) {
        $query->set( 'tag__not_in', 'array(ID OF THE FEATURED TAG)' );
    }
}
add_action( 'pre_get_posts', 'exclude_featured_tag' );

Эта функция имеет ловушку, которая вызывается после создания объекта переменной запроса, но до запуска фактического запроса.

Итак, насколько я понимаю, он принимает объект запроса в качестве входного параметра и изменяет (фактически фильтрует) его, выбирая все сообщения, исключая определенный тег (в моем случае featuredтег сообщения)

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

AndreaNobili
источник

Ответы:

33

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

ПЕРВАЯ ЧАСТЬ

Когда выполнять пользовательский запрос (это не полный список)

  • Для создания пользовательских слайдеров контента

  • Чтобы создать область рекомендуемого контента на странице

  • На шаблонах page.php если нужно отображать посты

  • Если вам требуется пользовательский контент на статической главной странице

  • Отображение связанных, популярных или информационных сообщений

  • Любой другой вторичный или дополнительный контент, выходящий за рамки основного запроса

Когда использовать основной запрос.

Для отображения основного контента на

ЧАСТЬ ВТОРАЯ

Чтобы выбрать все избранные посты, я использую эту строку, которая создает новый объект WP_Query, который определяет запрос с указанным тегом:

Итак, насколько я понимаю, это не основной запрос WordPres, а новый, созданный мной. Из того, что я понимаю, лучше создать новый запрос (как сделано) и не использовать основной запрос, когда я хочу выполнить этот вид операций.

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

НИКОГДА НЕ ИСПОЛЬЗУЙТЕ query_posts для создания пользовательских запросов или любого другого запроса. Мой акцент.

Примечание. Эта функция не предназначена для плагинов или тем. Как будет объяснено позже, есть более эффективные варианты для изменения основного запроса. query_posts () - это слишком упрощенный и проблемный способ изменить основной запрос страницы, заменив его новым экземпляром запроса. Он неэффективен (перезапускает SQL-запросы) и в некоторых обстоятельствах потерпит неудачу (особенно часто при разбивке на посты).

Двигаться дальше

Хорошо, продолжаю, я показываю все посты, которые не имеют тега Featured, для этого я использую этот фрагмент кода, который, напротив, изменяет основной запрос:

query_posts( array( 'tag__not_in' => array ( $term->term_id )));

Поэтому я думаю, что это довольно ужасно. Это правда?

Это все неправильно, и ваше утверждение, к сожалению, верно. Как уже было сказано, НИКОГДА не пользуйтесь query_posts. Он запускает совершенно новый запрос, что плохо сказывается на производительности, и в большинстве случаев нарушает нумерацию страниц, которая является неотъемлемой частью основного запроса для правильной работы нумерации страниц.

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

<?php
    if (have_posts()) :
        // Start the Loop.
        while (have_posts()) : the_post();

            get_template_part('content', get_post_format());

        endwhile;
    else :
        // If no content, include the "No posts found" template.
        get_template_part('content', 'none');

    endif;
?>

Вы можете полностью избавиться от этой части, удалить ее, записать и забыть об этом

<?
// get the term using the slug and the tag taxonomy
$term = get_term_by( 'slug', 'featured', 'post_tag' );
// pass the term_id to tag__not_in
query_posts( array( 'tag__not_in' => array ( $term->term_id )));
?>

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

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

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

add_action( 'pre_get_posts', 'exclude_featured_tag' );
function exclude_featured_tag( $query ) 
{
    if (    !is_admin() 
         && $query->is_home() 
         && $query->is_main_query() 
    ) {
        $query->set( 'tag__not_in', [ID OF THE FEATURED TAG] );
    }
}

ЧАСТЬ ТРЕТЬЯ

Дополнительный материал для чтения, который будет полезен в будущем

Питер Гусен
источник
С удовольствием. Рад, что вы нашли это полезным. Ендзё :-)
Питер Гусен
Вау, вполне ответ! Я упускаю одну важную информацию: как мне сказать WP «это страница постов» помимо главной страницы постов? Допустим, я хочу один список постов с категориями 10,11,12 и другой список с категориями 13,14,15. Я вижу, как я мог бы использовать pre_get_posts для вставки категорий в основной запрос, но как я могу сказать WP, чтобы он отображался как список постов с надлежащей нумерацией страниц? Должен ли я действительно следовать вашему обширному ответу здесь wordpress.stackexchange.com/a/215027/74134, потому что это страница? Конечно, WordPress изначально поддерживает несколько списков блогов на сайте?
Марк Берри