Использование post__in и post__not_in вместе?
Я пытаюсь показать только те посты, которые пользователь еще не видел, вот так:
$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 30,
'post__in' => $include,
'post__not_in' => $exclude,
'orderby' => 'post__in',
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => array($category_names),
'operator' => 'IN'
),
array(
'taxonomy' => 'category',
'field' => 'ID',
'terms' => array($category_ids),
'operator' => 'NOT IN'
)
)
);
$posts = get_posts($args);
Я ожидаю, что это вернет посты 4 и 5, но возвращаются 3, 4 и 5.
Как установить приоритет между параметрами 'post__in' и 'post__not_in'?
Я знаю, что мог бы использовать array_diff() для переменных $exclude и $include, но реальность сложнее, чем в этом вопросе. У меня есть много разных массивов для сравнения, и некоторые из них многомерные. Я также включаю и исключаю определенные таксономии.
Я также думаю, что другим легче читать, если это запрос WP_Query или $wpdb, чем множество строк PHP для получения параметров запроса.
Кроме того, если array_diff равен пустому массиву, то запрос фактически возвращает посты, а не пустой результат.
Возможно, лучший способ - это использовать вызов $wpdb или найти способ использовать meta_query из WP_Query для поля ID поста?
post__in
и post__not_in
являются взаимоисключающими параметрами.
Примечание: нельзя использовать post__in и post__not_in в одном запросе.
Как сформулирован ваш вопрос, очевидным решением (которое вы отвергаете) является использование array_diff
.
Если это решение действительно не подходит, вам понадобится фильтр для posts_where
(скорее всего), который обеспечит нужную логику запроса. Поскольку вы не объяснили, в чем именно заключается "более сложная реальность", невозможно предположить, какой должна быть эта логика.
Но вот пример фильтра posts_where
:
function smbd_cats_by_days ($where = '') {
// global $days_limit; // если это переменная
// $days_limit = DAYS_LIMIT; // если это константа
// $days_limit = get_option('days_limit',100);
// вам нужно раскомментировать одну из строк выше,
// в зависимости от выбранного механизма
$where .= " AND post_date < '" . date('y-m-d', strtotime("-{$days_limit} days")) . "'";
return $where;
}
add_filter('posts_where', 'smbd_cats_by_days');
Основываясь на правке вопроса и этом заявлении о намерениях:
Я пытаюсь показывать только те записи, которые пользователь еще не видел...
Напишите PHP-код для создания массива записей, которые пользователь уже видел, и исключите их с помощью post__not_in
. Ваша попытка включить всю логику в запрос только усложняет ситуацию.
Я также считаю, что другим разработчикам будет проще читать код, если это будет WP_Query или вызов $wpdb, а не множество строк PHP, которые в итоге просто формируют параметр запроса.
Когда вы напишете фильтры и/или SQL для включения всей логики в запрос, это не станет более "читаемым", да и изначально такой подход вызывает сомнения. Вы пытаетесь сделать это сложным путем. WP_Query
не предназначен для сложной логики, а сложная логика в SQL трудна для написания и понимания даже в лучшие дни.

или, возможно, posts_join
http://codex.wordpress.org/Plugin_API/Filter_Reference/posts_join

Параметры exclude и include нельзя использовать вместе, этот код используется в ядре, поэтому нужно выбрать что-то одно.
...
if ( ! empty($r['include']) ) {
$incposts = wp_parse_id_list( $r['include'] );
$r['posts_per_page'] = count($incposts); // только количество включенных записей
$r['post__in'] = $incposts;
} elseif ( ! empty($r['exclude']) )
...
Запрос $wpdb будет простым, если нужны только те аргументы, которые вы указали.
Этот способ прост, но если не сработает, сможете объяснить почему?
$exclude = array(1,2,3);
$include = array(3,4,5);
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => 30,
'post__in' => array_diff($include, $exclude),
)
$posts = get_posts($args);

Я знаю, что мог бы использовать array_diff() для переменных $exclude и $include, но реальность сложнее этого вопроса. Это должно быть сделано в запросе.

@s_ha_dum Извините, моя ошибка. Я не могу поставить минус вашему ответу.

Я обновил запрос, чтобы учесть все используемые параметры. Возможно, запрос через $wpdb будет лучшим вариантом.
