Когда нужно использовать WP_Query, query_posts() и get_posts()?

Такое ощущение, что половина учебников по Кодексу и вокруг блогосферы используют query_posts() , а другая половина WP_Query. Почему так?

Понравился вопрос? Нужен ответ? Поддержите проект
WPAsk
Ответов: 5
  1. Rarst

    Есть два разных контекста для циклов:

    • Основной цикл, который выполняется на основе URL-запроса и обрабатывается до загрузки шаблонов.
    • Дочерние циклы вызываются из файлов шаблона или иным образом

    Проблема с query_posts () заключается в том, что это вторичный цикл, который пытается быть основным и с треском проваливается. Таким образом, забудьте, что он существует.

    Для модификации основного цикла

    • не используйте query_posts()
    • используйте фильтр pre_get_posts с проверкой $query->is_main_query()

    Для запуска дочерних циклов

    Используйте new WP_Query или get_posts().

    Для очистки

    Используйте wp_reset_query() если вы использовали query_posts () или напрямую связались с глобальным $ wp_query .

    Используйте wp_reset_postdata() если вы использовали the_post () или setup_postdata () или перепутались с глобальным $ post и вам необходимо восстановить начальное состояние вещей, связанных с публикацией.

  2. Stephen Harris

    Например, вам не нужна нумерация страниц или липкие посты вверху — в этих случаях get_posts() более эффективен.

  3. Lukas Pecinka

    Существуют допустимые сценарии использования query_posts($query) , например:

    1. Вы хотите отобразить список постов или постов пользовательского типа на странице (используя шаблон страницы)

    2. Вы хотите, чтобы эти посты работали

    Теперь, почему вы хотите отобразить его на странице вместо использования шаблона архива?

    1. Это более интуитивно понятно для администратора (вашего клиента?) — они могут видеть страницу в разделе «Страницы»

    2. Лучше добавить его в меню (без страницы им бы пришлось добавить URL-адрес напрямую)

    3. Если вы хотите отобразить дополнительный контент (текст, миниатюру поста или любой другой мета контент) в шаблоне, вы можете легко получить его со страницы (и все это имеет больше смысла и для клиента). Посмотрите, использовали ли вы шаблон архива, вам нужно либо жестко закодировать дополнительный контент, либо использовать, например, параметры темы / плагина (что делает его менее понятным для клиента)

    Вот упрощенный пример кода (который будет на вашем шаблоне страницы — например, page-page-of-posts.php):

    /**
     * Template Name: Page of Posts
     */
    
    while(have_posts()) { // основной цикл - содержание страницы
      the_post();
      the_title(); // тайтл страницы
      the_content(); // контент страницы
      // ...
    }
    
    // теперь мы показываем список постов кастномго типа
    
    // сначала получить параметры пагинации
    $paged = 1;
    if(get_query_var('paged')) {
      $paged = get_query_var('paged');
    } elseif(get_query_var('page')) {
      $paged = get_query_var('page');
    }
    
    // отправлять запросы и заменять основной запрос (страницу) на этот (так что нумерация страниц работает)
    query_posts(array('post_type' => 'my_post_type', 'post_status' => 'publish', 'paged' => $paged));
    
    // пагинация
    next_posts_link();
    previous_posts_link();
    
    // цикл
    while(have_posts()) {
      the_post();
      the_title(); // тайл поста кастомного типа
      the_content(); // контент поста кастомного типа
    }
    
    wp_reset_query(); // устанавливает основной запрос (глобальный $wp_query) на исходный запрос страницы (он получает его из глобальной переменной $wp_the_query) и сбрасывает данные записи
    
    // Итак, теперь мы можем снова отобразить контент, связанный со страницей (если мы этого хотим)
    while(have_posts()) { // оригинальный основной цикл - содержание страницы
      the_post();
      the_title(); // тайтл страницы
      the_content(); // контент страницы
      // etc...
    }
    

    Также мы могли бы избежать использования здесь query_posts() и использовать вместо него WP_Query — например, так:

    // ...
    
    global $wp_query;
    $wp_query = new WP_Query(array('your query vars here')); // устанавливает новый пользовательский запрос в качестве основного запроса
    
    // пользовательский цикл пост-типа здесь
    
    wp_reset_query();
    
    // ...
    

    Но зачем нам это делать, когда у нас есть такая приятная маленькая функция?

    1. 2ndkauboy

      Это также можно сделать с помощью «pre_get_posts». Я сделал это, чтобы «статическая титульная страница» перечисляла мои собственные типы записей в произвольном порядке и с настраиваемым фильтром.

  4. prosti

    pre_get_posts — это фильтр для изменения любого запроса. Чаще всего он используется для изменения только «основного запроса»:

    На самом деле это хук действия. Это повлияет на любой запрос.

    Основной запрос отображается в ваших шаблонах следующим образом:

      if (have_posts ()):
        while (have_posts ()): the_post ();
           //The LOOP
        endwhile;
    endif;
     

    На самом деле, это тоже не так. Функция have_posts выполняет итерацию объекта global $wp_query , который не связан с основным запросом. global $wp_query; также можно изменить с помощью вторичных запросов.

      function have_posts () {
        global $wp_query;
        return $wp_query->have_posts ();
    }
     

    get_posts()

    По сути, это оболочка для отдельного экземпляра объекта WP_Query.

    На самом деле WP_Query является классом, поэтому у нас есть экземпляр класса.

Добавить ответ

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: