Постраничная навигация в wordpress без плагина (альтернатива wp-pagenavi)

CONCLUSION

This might seem like a really lot of overheads, and it might be, but the pro’s outweigh the con’s big time


BIG PRO’S

  • You do not need to alter the page template for the specific page in any way. This makes everything dynamic and can easily be transferred between themes without making modifications to the code whatsoever if everything is done in a plugin.

  • At most, you only need to create a template part in your theme if your theme does not have one yet

  • Any pagination that works on the main query will work on the page without any type of alteration or anything extra from the query being passed to function.

There are more pro’s which I cannot think of now, but these are the important ones

THE PAGE OBJECT

The current page object is available to display as a post by using the default loop on the page, separate and on top of the injected posts. If you do not need this, you can simply set to true, this will hide the page content from being displayed.

At this stage I’m using CSS to hide the page object through the and actions as I cannot find another way of doing this. The downside with this method is that anything hooked to action hook inside the main query will also be hidden by default if you hide the page object.

THE CLASS

The class can be improved and should be properly namespaced as well Although you can simply drop this in your theme’s functions file, it would be better to drop this into a custom plugin.

Use, modify and abuse as you see fit. The code is well commented, so it should be easy to follow and adjust

1) Стандартный Цикл и цикл на основе query_posts()

Я объединил 2 вида циклов (с  и начинающийся с  ), потому что технически они абсолютно одинаковые.

Давайте вспомним, как выглядит стандартный Цикл WordPress:

<?php
// проверяем есть ли посты в глобальном запросе - переменная $wp_query
if( have_posts() ){
	// перебираем все имеющиеся посты и выводим их
	while( have_posts() ){
		the_post();
		?>

		<div <?php post_class(); ?> id="post-<?php the_ID(); ?>">
			<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
			<?php the_content(); ?>
		</div>

		<?php
	}
	?>

	<div class="navigation">
		<div class="next-posts"><?php next_posts_link(); ?></div>
		<div class="prev-posts"><?php previous_posts_link(); ?></div>
	</div>

	<?php
}
// постов нет
else {
	echo "<h2>Записей нет.</h2>";
}

Такой код мы можем встретить в файлах index.php, category.php и т.д. Эти файлы отвечают за вывод на странице списка записей. Этот цикл перебирает по очереди посты, которые выводятся на странице и во время перебора, используя Теги Шаблона (предназначенные для использования внутри Цикла), мы можем вывести различные данные поста (заголовок, текст, метаданные и т.д.).

Обратите внимание: в стандартном Цикле мы не указываем никаких данных для выборки записей, а сразу начинаем цикл с if( have_posts() ){ while( have_posts() ){… Это говорит о том, что данные уже существуют и их нужно просто обработать и вывести на экран. «Уже существующие» данные сохраняются в глобальную переменную $wp_query и для каждого типа страниц WordPress определяются автоматически, т.е

WordPress заранее делает запрос к БД, на основе того какой тип страницы сейчас отображается (категория, метка, статья, постоянная страница и т.д.) и результат запроса записывается в $wp_query, а затем от туда выводится в цикле. Интересно, что такой запрос делается функцией query_posts(), которую мы разберем ниже

«Уже существующие» данные сохраняются в глобальную переменную $wp_query и для каждого типа страниц WordPress определяются автоматически, т.е. WordPress заранее делает запрос к БД, на основе того какой тип страницы сейчас отображается (категория, метка, статья, постоянная страница и т.д.) и результат запроса записывается в $wp_query, а затем от туда выводится в цикле. Интересно, что такой запрос делается функцией query_posts(), которую мы разберем ниже.

Обычный Цикл WordPress используется для базовых страниц WP (категории, метки, архивы по дате).

Событие pre_get_posts

function my_pre_get_posts( $query ) {
    if ( ! is_admin() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 5 );
    }
}
add_action( 'pre_get_posts', 'my_pre_get_posts' );

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

Результат такого подхода тот же, что и с , но в этот раз будет работать пагинация, а загрузка страницы будет происходить быстрее, поскольку с мы действительно изменили основной запрос перед его выполнением и не выполняли вторичных запросов.

Функция get_posts()

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

У функции есть предустановленные параметры. Их иногда нужно изменить, чтобы они не мешали получить нужный результат:

  • — по умолчанию выбираются записи типа
  • — по умолчанию выбираются пять записей
  • — параметр отключает работу некоторых фильтров (хуков)

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

Параметры по умолчанию:

// параметры по умолчанию
$posts = get_posts(
    'numberposts' => 5,
    'category'    => ,
    'orderby'     => 'date',
    'order'       => 'DESC',
    'include'     => array(),
    'exclude'     => array(),
    'meta_key'    => '',
    'meta_value'  =>'',
    'post_type'   => 'post',
    'suppress_filters' => true,
);

Пример использования функции:

<?php
global $post;
$lastposts = get_posts(
    'posts_per_page' => 3
);
?>
<?php foreach ($lastposts as $post) ?>
    <?php setup_postdata($post); ?>
    <h2>
        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    </h2>
    <p><?php the_excerpt(); ?></p>
<?php endforeach; ?>
<?php wp_reset_postdata(); ?>

То же самое с использованием класса :

<?php
$query = new WP_Query(
    'posts_per_page' => 3
);
?>
<?php while ($query->have_posts()) ?>
    <?php $query->the_post(); ?>
    <h2>
        <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
    </h2>
    <p><?php the_excerpt(); ?></p>
<?php endwhile; ?>
<?php wp_reset_postdata(); ?>

Функция возвращает глобальную переменную в правильное состояние, в соответствие с текущим основным запросом. Функцию нужно использовать каждый раз после запуска произвольного цикла. Т.е. в случаях, когда на странице есть дополнительный цикл WordPress с использованием глобальной переменной .

Changelog

Release Date – June 22, 2020

Added option to query by posts that share the same terms

Release Date – May 26, 2020

Fixed the Custom Field Value options

Release Date – May 03, 2020

Fixed “Post author is Archive author” query

1.0.9

Release Date – March 13, 2020

  • Fixed – Fixed Start and End Date options. IMPORTANT! For simplicity’s sake, we seperated the start and end dates option into two. So if you had a dynamic date range using this option, select “start date” and “end date” after updating.
  • New – Added order by comment count option
  • Tweak – Added better support for integration with custom query ids
  • Coming soon: User list widget

1.0.8

Release Date – March 12, 2020

  • New – Added an option to include or exclude current date/time from dynamic date range
  • New – Added extra support for multi valued field. Unfortunately, chackboxes are still not supported
  • Tweak – Fixed the labels a bit so that the query options are more clear

Related #Related

Uses

Uses
Uses
wp-includes/class-wp-user-query.php: WP_User_Query::fill_query_vars()
wp-includes/class-wp-user-query.php: WP_User_Query::parse_order()
wp-includes/class-wp-user-query.php: WP_User_Query::parse_orderby()
wp-includes/class-wp-user-query.php: pre_get_users
wp-includes/formatting.php: sanitize_key()
wp-includes/load.php: is_multisite()
wp-includes/functions.php: wp_parse_id_list()
wp-includes/functions.php: absint()
wp-includes/class-wp-date-query.php: WP_Date_Query::__construct()
wp-includes/plugin.php: do_action()
wp-includes/plugin.php: apply_filters()
wp-includes/plugin.php: do_action_ref_array()
wp-includes/class-wp-user-query.php: WP_User_Query::get_search_sql()
wp-includes/class-wp-user-query.php: user_search_columns
wp-includes/class-wp-user-query.php: pre_user_query
wp-includes/post.php: get_post_types()
wp-includes/ms-functions.php: wp_is_large_network()
wp-includes/wp-db.php: wpdb::prepare()
wp-includes/wp-db.php: wpdb::get_blog_prefix()
wp-includes/class-wp-meta-query.php: WP_Meta_Query::__construct()

Цикл на основе query_posts()

позволяет изменить базовый запрос и вывести нужный нам вариант записей.

Вариант 1

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

<?php
global $query_string; // параметры базового запроса
query_posts( $query_string .'&cat=-6,-9&order=ASC&posts_per_page=20' ); // базовый запрос + свои параметры 



wp_reset_query(); // сброс запроса
?>

В этом примере мы создали новый запрос к БД, в котором использовали параметры базового запроса + свои параметры: исключили категории 6 и 9 (), а также отсортировали записи по порядку () и вывели 20 записей на странице вместо, установленных в настройках 10 (). Полный список параметров, которыми можно сформировать нужный нам вывод, смотрите в описании функции query_posts().

Преимущества такого изменения в том, что если мы, например, изменим количество выводимых записей на странице с 10 (по умолчанию) на 20, то пагинация на странице автоматически подстроится под это изменение, потому что query_post() меняет данные глобальной переменной $wp_query, а пагинация строится именно на основе этих данных. Это лишь один из примеров, показывающий что query_posts() и поведение других функций на странице взаимосвязаны.


Изменять базовый запрос WP рекомендуется через фильтр pre_get_posts

Вариант 2

Можно не использовать параметры базового запроса ($query_string), а полностью переписать базовый запрос:

query_posts( 'cat=-6,-9&order=ASC' );

Однако, такой подход по сути сотрет базовый запрос и создаст новый, который может быть составлен неправильно, поэтому полностью переписывать базовый запрос нужно аккуратно, со знанием дела.

Необходимость

Сбрасывать измененный запрос при использовании нужно, потому что переписывает глобальную переменную $wp_query которая отвечает за некоторые свойства страницы. Давайте посмотрим на примере.

Предположим нам на странице категории 6 (ID категории), нужно вывести данные только поста 9 (ID поста):

<?php
query_posts('p=9');
if(have_posts()){ while(have_posts()){ the_post();
	the_title();
	the_content();
}}
else echo 'Записей нет';
?>

В этом примере мы не сбросили запрос и функция query_posts() переписала глобальную переменную $wp_query. Теперь, кода мы проверим какая это страница (а это страница категории: is_category() == true), мы увидим, что это уже совсем не страница категории, а страница поста: is_single() == true. Т.е. следующий код вернет нам «Это страница поста», хотя на самом деле это страница категории:

if( is_category() ) echo 'Это страница категории'; // не сработает
if( is_single() ) echo 'Это страница поста'; // сработает

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

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

Когда нужно немного изменить основной (базовый) запрос WordPress. В идеале: для исключения рубрики/метки (например, на главной странице); изменение направления сортировки; ограничения количества выводимых постов; исключения определенных постов из категории/метки и т.п.

Не нужно использовать query_posts() для создания нескольких циклов на одной странице, для вывода в сайдбар списка постов, для создания дополнительного вывода записей и т.п., для этих целей используйте циклы на основе get_posts(). К тому же, обе функции понимают параметры одинаково! Так зачем «платить» больше?..

Examples

below you will find an assortment of examples. Please note these examples use the object rather than the function, however the arguments and logic remain the same.

1. Single custom field value

In this example, we will find all posts that have a post_type of ‘event’ where the custom field ‘location’ is equal to ‘Melbourne’. The custom field ‘ location’ in this case could be a text field, radio button or select field (something that saves a single text value)

2. Multiple custom field values (text based values)

In this example, we will find all posts that have a post_type of ‘event’ where the custom field ‘location’ is equal to ‘Melbourne’ and the custom field ‘attendees’ is higher than 100. The custom field ‘ attendees’ in this case could be a number field, text field, radio button or select field (something that saves a single text value)

3. Multiple custom field values (array based values)

In this example, we will find all posts that have a post_type of ‘event’ where the custom field ‘location’ is equal to ‘Melbourne’ or ‘Sydney’. The custom field ‘ location’ in this case could be a multi-select or checkbox field (something that saves a serialized array value)

4. Sub custom field values

In this example, we will find all events that have a ‘city’ or either ‘Melbourne’ or ‘Sydney’. Each ‘city’ is added as a new row to a repeater field called ‘location’.

To successfully query sub field values, we need to remember that the row number is not known (there may be 1,2 or even 3 rows of repeater field data). Therefore, we need to use a LIKE clause in our SQL query to allow for a WILDCARD in the meta_key search. To do this, we create a custom filter to replace the standard ‘=’ with ‘LIKE’.

Update: Since the changed behaviour of esc_sql() in WordPress 4.8.3, it is not easy to use the % character as a placeholder for the following search and replace, instead, we recommend that you use the $ character as shown below.

Note: This method requires hooking into the posts_where filter, which is not guaranteed to run on all post queries. To overcome this, set suppress_filters to false in the argument array passed to get_posts() or WP_Query.

Dynamic $_GET parameters

This example shows how to use $_GET parameters (from the URL) to modify the query of a post type archive. This example assumes a post type exists for ‘event’ and that it’s archive exists at the url; .

The event post type contains a select field called ‘city’ with values such as ‘melbourne’ and ‘sydney’. By adding a parameter to the url, the query will be modified and only posts that match the ‘city’ will be shown; .

Что такое WP_Query?

— это класс WordPress. Поскольку это именно класс, то из этого следует что у него есть множество свойств, в которых будет храниться нужная нам информация.

Если хотите взглянуть на сам код WP_Query, то его можно найти, открыв файл .

Работа с будет осуществляться в четыре этапа:

  • передача аргументов запроса
  • выполнение запроса
  • прохождение по результату в цикле
  • завершение: сброс данных постов

На практике это будет выглядеть примерно так:

<?php

$args = array(
    // аргументы
);

// Собственный запрос
$query = new WP_Query( $args );

// Проверка на наличие результата
if ( $query->have_posts() ) {

    // Прохождение по результатам в цикле
    while ( $query->have_posts() ) {

        $query->the_post();

    }

}

// Восстановление оригинальных данных
wp_reset_postdata();

?>

Аргументы можно передать непосредственно при создании класса, но я предпочитаю разделять эти вещи.

Сброс данных постов

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

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

Если этого не сделать, то в результате выполнения последующих запросов может быть извлечено не корректное содержимое, что повлияет на условные выражения и многое другое.

Notes

I updated the answer and removed the query-object part modification, based on the suggestion from @PieterGoosen, since it could e.g. break the breadcrumbs on his setup.

Also removed the check within the hook, since it might still give some irregularities in some cases. The reason is that the query-object is not always available. This is being worked on, see e.g. #27015. There are workarounds possible if we want to use the or .

I constructed the following table, just to get a better overview of some of the properties and query varaiables of the main object, for a given slug:


It’s that the pagination in depends on the not being set and the current page not being singular (from the 4.4 ):

where we can see that the part of the generated SQL query is within the conditional check. This explains why we modify the property above.

We could have used other filter/hooks, but here we used as mentioned by the OP.

Description

This plugin lets you create new WP queries as widgets and use shortcodes for queries on your pages. It also allows you to override the way category and tag pages display.

Query Wrangler’s interface is highly intuitive way to create queries and will be second nature for any Drupal Views user.

This plugin will bring extreme flexibility to WordPress users with its ability to create custom queries using the WP_Query class with a user interface.

Supports:

  • Most post data, including meta fields
  • Taxonomy data
  • Advanced Custom Fields
  • Custom Content Type Manager
  • Some exposed filters

Some examples of how you would use this plugin include:

THE MAIN QUERY

The following changes was done to the main query through the respective filters and actions

  • In order to paginate the main query:

    • The injector query’s property value is passes to that of the main query object through the filter

    • Set the value of the user passed parameter to the main query through

    • is calculated using the amount of posts in and . Because is true on pages, it inhibits the clause being set. Simply setting to false caused a few issues, so I decided to set the clause through the filter. I kept the of the clause set to to avoid 404’s on paged pages

This takes care of pagination and any issue that might arise from the post injection

Getting started

If you are already familiar with the above function, object and filter you may skip this section.

The WP_Query object is used to query posts and will return an object containing an array of $post objects and many useful methods.

The get_posts function makes use of the above WP_Query object, however, it only returns an array of $post objects making it a simpler way to find and loop over posts.

The pre_get_post filter is called after the query object is created, but before the actual query is run.

Example

This example demonstrates how to query all posts and display them in a list. Please note the functions and are used to allow functions such as and to work as expected.

Использование

В обоих следующих примерах выводятся ссылки на 5 самых комментируемых записей на блоге:

/*
 * в массиве задаем все необходимые параметры (более подробно о параметрах чуть ниже)
 */
$args = array(
    'posts_per_page' => 5,
    'orderby' => 'comment_count'
);
/*
 * создаем новый объект
 */
$q = new WP_Query($args);
/*
 * проверяем, существуют ли посты по заданным параметрам(необязательно)
 */
if($q->have_posts()) {
    /*
     * затем запускаем цикл
     */
    while($q->have_posts()){ $q->the_post();
        /*
         * выводим например ссылку на каждый пост
         */
        echo '<a  . get_permalink() . '">' . get_the_title() . '</a>';
    }
}
/*
 * восстанавливаем глобальную переменную $post
 */
wp_reset_postdata();

В этом примере мы не трогаем глобальную переменную $post, а также задаем параметры класса в виде строки:

$q = new WP_Query("posts_per_page=5&orderby=comment_count");
if($q->have_posts()) {
    while($q->have_posts()){ $q->next_post();
        $post_id = $q->post->ID;
        echo '<a href="' . get_permalink($post_id) . '">' . get_the_title($post_id) . '</a>';
    }
}

Дальше пойдет описание параметров, ещё есть отдельный пост про методы и свойства.

Основные и вторичные запросы

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

Вторичный запрос это тот, который выполняется дополнительно к основному. Например:

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

Основным отличием от других вспомогательных функций является то, что заменяет основной цикл на новый, вторичный цикл WordPress. Это значит, что в цикле с мы можем работать так же, как и в обычном основном цикле.

Для сравнения рассмотрим цикл для вывода популярных записей с помощью :

// Вторичный цикл
$popular = new WP_Query( ... );
while ( $popular->have_posts() ) {
    $popular->the_post();

    the_title(); // вывести название
    the_content(); // вывести содержимое
}
wp_reset_postdata();

Этот же цикл с помощью :

// Вторичный цикл
query_posts( ... );
while ( have_posts() ) {
    the_post();

    the_title(); // вывести название
    the_content(); // вывести содержимое
}
wp_reset_query();

Безусловно второй вариант выглядит немного чище и привычнее, поскольку такая конструкция чаще всего встречается при работе с основным циклом WordPress.

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

POST INJECTION QUERY


In order to accomplish post injection, I used a custom query to return the posts needed for injection. I also used the custom query’s property to adjust that of the main query to get pagination working from the main query. Posts are injected into the main query through the action.

In order to make the custom query accessible and usable outside the class, I introduced a couple of actions.

  • Pagination hooks in order to hook pagination funtions:

  • Custom counter which counts the posts in the loop. These actions can be used to alter how posts are displayed inside the loop according to post number

  • General hook to access the query object and current post object

    pregetgostsforgages_current_post_and_object

These hooks gives you a total hands-off experience as you do not need to change anything in the page template itself, which was my original intention from the start. A page can completely be altered from a plugin or a function file which makes this very dynamic

I have also used in order to load a template part which will be used to display the posts on. Most themes today make use of template parts, that makes this very useful in the class. If your theme uses , you can simply pass to to load .

If you need post format support for template parts, it is easy, you can still just pass to and simply set to and a template part will be loaded for a post with a post format of

$wp_query и $wp_the_query

После выполнения основного запроса WordPress помещает его результат в глобальную переменную , а в глобальной переменной хранится всего лишь ссылка на . Функции , и прочие работают именно с глобальным объектом .

Чтобы в этом убедиться достаточно взглянуть на реализацию подобных функций:

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

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

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

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

function wp_reset_query() {
    $GLOBALS = $GLOBALS;
    wp_reset_postdata();
}

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

2) Цикл на основе WP_Query()

Для вывода записей никак не связанных со страницей или создания множественных (дополнительных) циклов можно использовать циклы на основе класса WP_Query. Выглядят они аналогично циклам с использование . Для  используются те же самые параметры, что и для query_posts().

Интересно, что WP_Query является ядром функций и , т.е. обе эти функции работают на основе этого класса.

Пример цикла: выведем все записи из категории 9:

<?php
// указываем категорию 9 и выключаем разбиение на страницы (пагинацию)
$query = new WP_Query( 'cat=9&nopaging=1' ); 
if( $query->have_posts() ){
	while( $query->have_posts() ){
		$query->the_post();
		?>
		<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
		<?php the_content(); ?>
		<?php
	}
	wp_reset_postdata(); // сбрасываем переменную $post
} 
else
	echo 'Записей нет.';
?>

Пример создания множественных циклов на основе :

<?php
// Цикл 1
$query1 = new WP_Query('cat=-1&nopaging=1'); // все посты, кроме категории 1
while( $query1->have_posts() ){
	$query1->the_post();

	// вывод записей
}
wp_reset_postdata();

// Цикл 2
$query2 = new WP_Query('cat=-2&nopaging=1'); // все посты, кроме категории 2
while( $query2->have_posts() ){
	$query2->the_post();

	// вывод записей
}
wp_reset_postdata();

// Цикл 3
$query3 = new WP_Query('cat=-3&nopaging=1'); // все посты, кроме категории 3
while( $query3->have_posts() ){
	$query3->the_post();

	// вывод записей
}
wp_reset_postdata();
?>

Особенность циклов на WP_Query() в том, что мы создаем новый объект , который никак не связан с аналогичным глобальным объектом $wp_query и поэтому мы никак не нарушаем структуру текущей страницы.

Также, мы можем использовать новый объект в других целях, не только для вывода записей, но и для различного рода проверок: например, записи какого типа страницы  используются в этом новом объекте; можем узнать общее количество записей удовлетворяющих запросу () и т.д. Такие данные могут пригодится при создании дополнительных запросов с пагинацией или где-то еще ().

Зачем нужно использовать ?

В глобальной переменной  хранятся данные текущего поста (если показывается страница поста, то данные этого поста). Когда срабатывает часть кода $query->the_post(), то в переменную $post записываются данные текущего поста в цикле и в конце цикла в этой переменной остаются данные последнего поста из этого цикла, а нужно чтобы $post всегда содержала данные текущего поста страницы. Т.е. получается до использования цикла $post->ID (ID текущего поста) было равно, допустим, 10, а после срабатывания цикла, та же самая переменная $post->ID уже равна, допустим, 56 (ID последнего поста из цикле), а нужно чтобы она по-прежнему равнялась 10.

wp_reset_postdata() используется как раз для того, чтобы вернуть правильные данные в переменную $post.

Когда использовать ?

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

WP_Query PHP код для вывода записей в разделе ТЕГОВ

Вывод записей в тегах, в отличии от категорий, немного другой. По какой-то причине, в тегах не работает функция исключающая категории из WP_Query:

‘cat’ => ‘-310’

К счастью, работает другая структура:

‘category__not_in’ => ‘310’

И код вывода $wp_query для тегов будет такой:

<?php // Произвольное поле по которому будет сортировка $the_key = ‘1Year’; $args = array(     ‘meta_key’ => $the_key,     // Сортируем по значению цифры в произвольном поле     ‘orderby’ => ‘meta_value_num’,     // Сортируем от большего к меньшему     ‘order’ => ‘DESC’,     // Исключаем категории     ‘category__not_in’ => ‘310’ ); global $wp_query; query_posts(     array_merge(         $wp_query->query,         $args     ) ); ?>

WP_Query PHP код для вывода записей в КАТЕГОРИЯХ

Самый простой вывод постов, исключающий записи из конкретных категорий. Использую его для вывода на главной странице через index.php или home.php.

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

<?php query_posts($query_string.’&cat=-1,-169,-40,-91′); ?>

Иногда в код, который выводит все статьи, но исключает определенные рубрики, требуется добавить пагинацию (&paged=’.$paged;), чтобы в последний страницах навигации не было пустых страниц.

В коде ниже выводятся записи с сортировкой по произвольному полю с ДАТОЙ. Выводятся записи с произвольным полем год, затем сортируются от последнего года к предыдущему.

<?php // Произвольное поле по которому будет сортировка $the_key = ‘1Year’; $args = array(     ‘meta_key’ => $the_key,     // Сортируем по значению цифры в произвольном поле     ‘orderby’ => ‘meta_value_num’,     // Сортируем от большего к меньшему     ‘order’ => ‘DESC’,     // Исключаем категории     ‘cat’ => ‘-310’ ); global $wp_query; query_posts(     array_merge(         $wp_query->query,         $args     ) ); ?>


С этим читают