Когда использовать WP_query (), query_posts () и pre_get_posts

Я вчера считал @nacin Вы не знаете Запроса и был отправлен вниз что-то вроде кроличьей норы запросов. Прежде вчера, я (неправильно) использовал query_posts() для всех моих запросов потребностей. Теперь я немного более мудр об использовании WP_Query(), но все еще имейте некоторые серые области.

Что я думаю, что знаю наверняка:

Если я делаю дополнительные циклы где-нибудь на странице — на боковой панели, на нижнем колонтитуле, каком-либо виде "связанных сообщений", и т.д. — я хочу использовать WP_Query(). Я могу неоднократно использовать это на единственной странице без любого вреда. (право?).

Что я не знаю наверняка

  1. Когда делают я использую @nacin pre_get_posts по сравнению с. WP_Query()? Если я использую pre_get_posts для всего теперь?
  2. То, когда я хочу изменить цикл на шаблонной странице — позволяет, говорят, что я хочу изменить страницу архива таксономии — делают я удаляю if have_posts : while have_posts : the_post часть и запись мое собственное WP_Query()? Или сделайте я изменяю выходное использование pre_get_posts в моем functions.php файле?

tl; доктор

tl; доктор постановляет, что я хотел бы потянуть из этого:

  1. Никогда не используйте query_posts больше
  2. При выполнении нескольких запросов на единственной странице использовать WP_Query()
  3. При изменении цикла сделайте этот __________________.

Спасибо за любую мудрость

Terry

PS: Я видел и читал: Когда необходимо использовать WP_Query по сравнению с query_posts () по сравнению с get_posts ()? Который добавляет другой размер — get_posts. Но не имеет дело с pre_get_posts вообще.

163
13.04.2017, 15:37
3 ответа

Вы правы сказать:

Никогда не используйте query_posts больше

pre_get_posts

pre_get_posts фильтр, для изменения любого запроса. Это чаще всего используется для изменения только 'основного запроса':

add_action('pre_get_posts','wpse50761_alter_query');
function wpse50761_alter_query($query){

      if( $query->is_main_query() ){
        //Do something to main query
      }
}

(Я также проверил бы это is_admin() возвращает false - хотя это может быть избыточно.). Основной запрос появляется в Ваших шаблонах как:

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

Если Вы когда-нибудь чувствуете потребность отредактировать этот цикл - использование pre_get_posts. т.е. Если Вы испытываете желание использовать query_posts() - использовать pre_get_posts вместо этого.

WP_Query

Основной запрос является важным экземпляром a WP_Query object. WordPress использует его для решения, который шаблон использовать, например, и любые аргументы передал в URL (например, разбиение на страницы) все направлены в тот экземпляр WP_Query объект.

Для вторичных циклов (например, на боковых панелях, или 'связанных сообщениях' списки) Вы захотите создать свой собственный отдельный экземпляр WP_Query объект. Например.

$my_secondary_loop = new WP_Query(...);
if( $my_secondary_loop->have_posts() ):
    while( $my_secondary_loop->have_posts() ): $my_secondary_loop->the_post();
       //The secondary loop
    endwhile;
endif;
wp_reset_postdata();

Заметить wp_reset_postdata(); - это вызвано тем, что вторичный цикл переопределит глобальное $post переменная, которая определяет 'текущее сообщение'. Это по существу сбрасывает это к $post мы идем.

get_posts ()

Это - по существу обертка для отдельного экземпляра a WP_Query объект. Это возвращает массив объектов сообщения. Методы, используемые в цикле выше, больше не доступны Вам. Это не 'Цикл', просто массив объекта сообщения.

<ul>
<?php
global $post;
$args = array( 'numberposts' => 5, 'offset'=> 1, 'category' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) :  setup_postdata($post); ?>
    <li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; wp_reset_postdata(); ?>
</ul>

В ответ на Ваши вопросы

  1. Использовать pre_get_posts изменить Ваш основной запрос. Используйте отдельное WP_Query объект (метод 2) для вторичных циклов на шаблонных страницах.
  2. Если Вы хотите изменить запрос основного цикла, использовать pre_get_posts.
151
19.02.2020, 21:54
  • 1
    Так есть ли какой-либо сценарий, когда можно было бы перейти прямо к get_posts (), а не WP_Query? –  urok93 25.08.2012, 19:09
  • 2
    @drtanz - да. Скажите, например, что Вам не нужно разбиение на страницы или липкие сообщения наверху - в этих экземплярах get_posts() более эффективно. –  Stephen Harris 25.08.2012, 21:00
  • 3
    Но разве который не добавил бы дополнительный запрос, где мы могли просто изменить pre_get_posts для изменения основного запроса? –  urok93 26.08.2012, 23:54
  • 4
    @drtanz - Вы не использовали бы get_posts() для основного запроса - для вторичных запросов. –  Stephen Harris 27.08.2012, 01:42
  • 5
    @StephenHarris =) При использовании next_post () на объекте вместо того, чтобы использовать the_post Вы не ступаете на глобальный запрос и не должны помнить использовать wp_reset_postdata впоследствии. –  Privateer 19.09.2015, 21:01

Существует два различных контекста для циклов:

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

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

Изменить основной цикл

  • не использовать query_posts()
  • использовать pre_get_posts фильтр с $query->is_main_query() проверить
  • поочередно используйте request фильтр (немного слишком грубо так выше лучше),

Выполнять вторичный цикл

Использовать new WP_Query или get_posts() то, которые являются в значительной степени взаимозаменяемыми (последний является тонкой оберткой для формирователя).

К очистке

Использовать wp_reset_query() если Вы использовали query_posts() или смешанный с глобальным $wp_query непосредственно - таким образом, Вы почти никогда не должны будете.

Использовать wp_reset_postdata() если Вы использовали the_post() или setup_postdata() или смешанный с глобальным $post и должен восстановить начальное положение постсвязанных дел.

57
19.02.2020, 21:54

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

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

  2. Вы хотите сделать разбиение на страницы тех сообщений работой

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

  1. Это более интуитивно для администратора (Ваш клиент?) - они видят страницу на 'Страницах'

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

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

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

/**
 * Template Name: Page of Posts
 */

while(have_posts()) { // original main loop - page content
  the_post();
  the_title(); // title of the page
  the_content(); // content of the page
  // etc...
}

// now we display list of our custom-post-type posts

// first obtain pagination parametres
$paged = 1;
if(get_query_var('paged')) {
  $paged = get_query_var('paged');
} elseif(get_query_var('page')) {
  $paged = get_query_var('page');
}

// query posts and replace the main query (page) with this one (so the pagination works)
query_posts(array('post_type' => 'my_post_type', 'post_status' => 'publish', 'paged' => $paged));

// pagination
next_posts_link();
previous_posts_link();

// loop
while(have_posts()) {
  the_post();
  the_title(); // your custom-post-type post's title
  the_content(); // // your custom-post-type post's content
}

wp_reset_query(); // sets the main query (global $wp_query) to the original page query (it obtains it from global $wp_the_query variable) and resets the post data

// So, now we can display the page-related content again (if we wish so)
while(have_posts()) { // original main loop - page content
  the_post();
  the_title(); // title of the page
  the_content(); // content of the page
  // etc...
}

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

// ...

global $wp_query;
$wp_query = new WP_Query(array('your query vars here')); // sets the new custom query as a main query

// your custom-post-type loop here

wp_reset_query();

// ...

Но, почему мы сделали бы это, когда мы имеем такую миленькую функцию в наличии для него?

24
19.02.2020, 21:54
  • 1
    Brian, спасибо за это. Я изо всех сил пытался заставить pre_get_posts работать на странице в ТОЧНО сценарии, который Вы описываете: клиент должен добавить пользовательские поля/содержание к тому, что иначе было бы страницей архива, таким образом, "страница" должна быть создана; клиент должен видеть что-то для добавления к военно-морскому меню как добавление, что настраиваемая ссылка выходит из них; и т.д. +1 от меня! –  Will Lanni 13.12.2012, 13:07
  • 2
    Это может также быть сделано с помощью "pre_get_posts". Я сделал это, чтобы иметь "статическую первую полосу" список моих пользовательских типов сообщения в пользовательском порядке и с пользовательским фильтром. Эта страница также нумеруется страницы. Проверьте этот вопрос видеть, как он работает: wordpress.stackexchange.com/questions/30851 / … Так короче говоря, нет все еще никакого более законного сценария для использования query_posts ;) –  2ndkauboy 12.01.2015, 16:47
  • 3
    Поскольку "Нужно отметить, что с помощью этого для замены основного запроса на странице может увеличить времена загрузки страницы в худших вариантах развития событий, более чем удваивающих необходимый объем работы или больше. В то время как простой в использовании, функция также подвержена беспорядку и проблемам позже". Получите codex.wordpress.org/Function_Reference/query_posts –  Claudiu Creanga 09.03.2015, 18:31
  • 4
    , Этот ответ является всеми видами несправедливости. Можно создать" Страницу "в WP с тем же URL как Пользовательский тип сообщения. EG, если Вашим CPT являются Бананы, можно получить страницу под названием Бананы с тем же URL. Затем Вы закончили бы с siteurl.com/bananas. Пока у Вас есть архив-bananas.php в Вашей папке темы, затем это будет использовать шаблон, и" переопределяют "ту страницу вместо этого. Как указано в одном из других комментариев, с помощью этого" метода "создает дважды рабочую нагрузку для WP, таким образом никогда не должен использоваться. –  Hybrid Web Dev 19.06.2015, 23:07

Теги

Похожие вопросы