Почему post__not_in лучше не использовать?

Параметр WP_Query post__not_in супер-полезен, как минимум с его помощью можно исключать текущий пост, когда выводите похожие посты. Однако для высоконагруженных сайтов это может привести к моментикам с производительностью, потому что использование этого параметра исключает возможность кэширования запроса.

Вот допустим пример вывода последних постов на странице поста, но с исключением из цикла текущего поста:

$exclude_id = get_the_ID();
 
$args = array(
	'posts_per_page' => 10,
	'post_status' => 'publish',
	'post__not_in' => array( $exclude_id ),
);
 
$recent_posts = new WP_Query( $args );
 
echo '<h2>Свежие посты</h2>';
 
while( $recent_posts->have_posts() ) : $recent_posts->the_post();
	the_title( '<h3><a href="' . get_permalink() . '">', '</a></h3>' );
endwhile;
 
wp_reset_postdata();

Выглядит как лёгкое и чистое решение, не так ли? Но не спешите радоваться, ведь как раз от подобного решения мы сейчас и будем пытаться уйти.

Объясняю почему.

Дело в том, что запрос, который мы построили выше, теперь будет уникальным для каждого поста, потому что в нём будет присутствовать часть AND ID NOT IN ( '12345' ), это по сути и ломает идею кэширования, потому что так как запрос уникальный, то и кэш будет уникальным для каждого запроса и в итоге, вместо того, чтобы всего-то получить последние посты из кэша, у нас будет происходить подключение к базе данных и полноценно вся работа.

Конечно, на обычных сайтах это не сильно нас напряжёт, но на сайтах с сотнями тысяч постов вы это точно почувствуете.

Как же мы можем переделать наш предыдущий пример в таком случае?

$exclude_id = get_the_ID();
 
// мы знаем, что один пост вероятно исключим, поэтому получаем не 10, а 11
$args = array(
	'posts_per_page' => 11,
	'post_status' => 'publish'
);
 
$recent_posts = new WP_Query( $args );
 
echo '<h2>Свежие посты</h2>';
 
// нам понадобится счётчик, потому что не факт, что исключаемый пост будет в цикле
// а значит без счётчика у нас будет выводиться то 10, то 11 – не порядок
$count = 0;
 
while( $recent_posts->have_posts() && $count < 10 ) : $recent_posts->the_post();
 
	if( $recent_posts->post->ID === $exclude_id ) {
		continue; // скипаем итерацию цикла, если это исключаемый пост
	}
 
	the_title( '<h3><a href="' . get_permalink() . '">', '</a></h3>' );
	$count++;
endwhile;
 
wp_reset_postdata();

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.

Миша Рудрастых и WordPress

Полезности из мира WordPress и жизни студии.

Мой телеграм-канал