Intereting Posts
Как использовать запрос wpdb для построения маркеров в API Карт Google? Получил белую пустую страницу после копирования функции functions.php в дочернюю тему параметр rewrite get с настраиваемым типом сообщения Как я могу получить следующий идентификатор сообщения после текущего идентификатора сообщения для пользовательского типа сообщения Force index.php has_posts () loop для выхода, если не найдены липкие сообщения Исключить почтовый формат из next_post и prev_post Действия в соответствии с типом и размером изображения Рефакторинг длинной if / else php-цепей Лучший способ хранить ежедневные просмотры сообщений? Виджет: html 2-мерный массив не работает Добавить классы Bootstrap для последних сообщений Widget Переводы разрешены, но существуют некоторые проблемы запрос сообщение по автору пол Шрифт отображается как Arial вместо Times Отображать таксономии пользовательских сообщений в виде страницы архива

Временно переписывает $ wp_query плохую идею?

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

Я могу обойти проблему, перезаписав основной запрос (или перезаписав глобальный $wp_query содержащий основной запрос, основной запрос все еще существует) с моим пользовательским запросом и сбросом основного запроса, как только я закончу. Это также означает, что я могу использовать один и тот же цикл для основного запроса и моих пользовательских запросов. Например:

 // Query if ( $i_need_a_custom_query ) { $wp_query = new WP_Query($custom_query_args); } // The Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); // Do some loop stuff // and call some functions that rely on the main query // End the loop endwhile; endif; // I'm done so reset the query wp_reset_query(); 

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

  • Правильно ли я устал переписывать основной запрос?
  • Есть ли какие-то побочные эффекты?
  • И правильно ли я предполагаю, что вызов wp_reset_query() не является дорогостоящим (т. wp_reset_query() Он фактически не перезапускает запрос, а просто перезагружает глобальные переменные, которые все еще находятся где-то)?

Изменить, чтобы уточнить:

Я использую только специальные запросы в качестве вторичных запросов, вот и весь вопрос. Я хочу использовать один и тот же шаблон. Я использую специальный вторичный запрос или используя основной запрос. Я понимаю, что то, что я делаю, по существу то же самое, что и с использованием query_posts() , что является плохой идеей. Насколько мне известно и в широком смысле, два недостатка в использовании query_posts() – это 1. Производительность, которая не является проблемой, потому что я делаю это только при выполнении вторичного пользовательского запроса и 2. Неумышленные последствия изменения глобальный $ wp_query, который именно то, что я действительно хочу (и, как я сказал, действительно работает отлично).

Solutions Collecting From Web of "Временно переписывает $ wp_query плохую идею?"

В общем, я согласен с Howdy_McGee в том, что следует избегать перезаписи основного запроса, если это абсолютно необходимо – чаще всего изменение основного запроса с чем-то вроде 'pre_get_posts' является лучшим решением для таких сценариев.

Ручная перезапись глобальной $wp_query может вызвать все виды непреднамеренного поведения, если вы не слишком осторожны, в том числе разбиваете разбивку на страницы, среди прочего. По сути, это еще более упрощенный эквивалент часто критикуемой функции query_posts() , о которой говорится в кодексе WordPress Code Reference :

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

Однако в этом случае, где вам требуется:

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

то одно решение заключается в том, чтобы хранить «контекстный» экземпляр WP_Query в локальной переменной и вызывать условные методы WP_Query для этой переменной вместо использования их глобально доступных условных тегов функций (которые всегда явно ссылаются на основной запрос, global $wp_query ).

Например, если вы хотите, чтобы ваша «контекстная переменная запроса» ссылалась на пользовательский вторичный запрос в одиночных и архивных шаблонах для вашего настраиваемого типа сообщений, my-custom-post-type , но обратитесь к основному запросу в каждом другом случае, вы может сделать следующее:

Файл functions.php темы или файл плагина:

 function wpse_232115_get_contextual_query() { global $wp_query; static $contextual_query; // A convenient means to check numerous conditionals without a bunch of '||' operations, // ie "if( $i_need_a_custom_query )" if( in_array( true, [ is_singular( 'my-custom-post-type' ), is_post_type_archive( 'my-custom-post-type' ) ] ) ) { // Create the contextual query instance, if it doesn't yet exist if( ! isset( $contextual_query ) ) { $query_args = [ //... ]; $contextual_query = new WP_Query( $query_args ); } return $contextual_query; } return $wp_query; } 

Файлы общих файлов шаблонов «Generic»:

 $query = wpse_232115_get_contextual_query(); // Contextual Query loop (loops through your custom query when 'my-custom-post-type's // are being displayed, the main $wp_query otherwise. if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); // Tags dependent on The Loop will refer to the contextual query if The Loop // was set up with the "$query->" prefix, as above. Without it, they always // refer to the main query. the_title(); // The global conditional tags always refer to the main query if( is_singular() ) { //... Do stuff is the main query result is_singular(); } // Conditional methods on the $query object reference describe either // the main query, or a custom query depending on the context. if( $query->is_archive() ) { //... Do stuff if the $query query result is an archive } // End the loop endwhile; endif; 

Я не уверен, что это лучшее решение, но я думаю, что я подошел бы к этой проблеме.

Я чувствую, что вы должны использовать get_template_part() для разметки. Допустим, у вас есть пользовательский шаблон и блог, который использует тот же get_template_part() . Вы вызывали бы template_part в цикле вместо вызова The Loop в части. Например:

Ваш пользовательский шаблон

 $custom_query = new WP_Query( $args ); if ( $custom_query->have_posts() ) { while ( $custom_query->have_posts() ) { $custom_query->the_post(); get_template_part( $path ); } wp_reset_postdata(); } 

Ваш блог

 if ( have_posts() ) { while ( have_posts() ) { the_post(); get_template_part( $path ); } } 

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


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

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

 function query_posts($query) { $GLOBALS['wp_query'] = new WP_Query(); return $GLOBALS['wp_query']->query($query); } 

Помните, что $GLOBALS['wp_query'] === $wp_query . Теперь посмотрите на свой код, и вы обнаружите, что это то же самое.

Есть более чем достаточно query_posts о том, насколько плохи query_posts , поэтому не query_posts и работайте над ними.

Никогда не существует веской причины для замены основного запроса на любой странице. Замена основного запроса ВСЕГДА приведет к некоторой проблеме, она может быть не видна сразу, но вы обязательно увидите ее эффект.

Вы также должны помнить, что если вы после SEO и производительности, то действительно плохая новость заключается в том, что вы определенно делаете это неправильно. Основной запрос всегда выполняется нормально при любой загрузке страницы, т. Е. Он будет запрашивать db и возвращать соответствующие сообщения для страницы. Простое удаление цикла НЕ останавливает основной запрос. Если вы замените цикл на пользовательский, как и в вашем примере, вы снова запросите db, что означает, что вы делаете в два раза больше запросов, а также замедляете страницу из-за этого. Это негативно влияет на SEO, поэтому вам есть о чем подумать.

В заключение, если вам нужно что-то еще из основного запроса, ВСЕГДА используйте pre_get_posts чтобы изменить его. Таким образом, вы не запускаете никаких дополнительных запросов или разбиваете глобальные переменные