Основной запрос WordPress — это запрос, который выполняется до вывода какого-либо текста на страницу (на раннем этапе). Параметры такого запроса собирает сам WP опираясь на запрошенный URL, настройки ЧПУ и др. Так WordPress определяет сколько записей показать на странице, записи из какой рубрики показывать и т.д.

А вторичный запрос это тот, который создается пользователем (темой, плагином) и выполняется дополнительно к основному. Например: Вывод в сайдбаре списка популярных записей; Вывод комментируемых записей.

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

Разница между query_posts() и WP_Query в том, что query_posts() создает новый WP_Query объект и связывает его с глобальной переменной $wp_query, тогда как get_posts() или WP_Query() создает новый WP_Query объект, без изменения каких-либо глобальных данных.

Самым частым результатом использования query_posts() является сломанная пагинация, когда например первые две страницы работают, а третья и четвертая возвращают ошибку 404.

Наиболее правильным способом изменить основной цикл WordPress является событие pre_get_posts, которое происходит перед каждым запросом WP_Query. Работать с этим событием можно в плагине или в файле functions.php вашей темы.

Альтернативы query_posts()

Если вам необходимо выполнить вторичный запрос в WordPress, воспользуйтесь функцией get_posts() или конструкцией new WP_Query(). При работе с ними ваш код будет более явным и понятным для читающих.

Когда вам необходимо изменить основной запрос WordPress перед его выполнением, самым простым способом является событие pre_get_posts, или фильтр request, который выполняется еще раньше, чем pre_get_posts и только для основного запроса.

avoid_query_posts