最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

wp query - Use post__in and post__not_in together?

programmeradmin0浏览0评论

I'm trying to only show posts that a user hasn't seen, like this:

$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);

I'd expect this to return posts 4 and 5, but it returns 3, 4, and 5.

How do I set which gets preference between 'post_in' and the 'post_not_in' parameters?

I know that I could use array_diff() on the $exclude and $include variables, but the reality is more complicated than this question. I have many different arrays to compare against, and some of them are multidimensional. I'm also including and excluding certain taxonomies.

I also think it's easier for others to read if it's a WP_Query or $wpdb call, rather than lines and lines of PHP to end up with a query parameter.

Also, if array_diff equal an empty array, then the query actually returns posts, not nothing.

So perhaps the best way is a $wpdb call, or a way to use WP_Query's meta_query on the post ID field?

I'm trying to only show posts that a user hasn't seen, like this:

$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);

I'd expect this to return posts 4 and 5, but it returns 3, 4, and 5.

How do I set which gets preference between 'post_in' and the 'post_not_in' parameters?

I know that I could use array_diff() on the $exclude and $include variables, but the reality is more complicated than this question. I have many different arrays to compare against, and some of them are multidimensional. I'm also including and excluding certain taxonomies.

I also think it's easier for others to read if it's a WP_Query or $wpdb call, rather than lines and lines of PHP to end up with a query parameter.

Also, if array_diff equal an empty array, then the query actually returns posts, not nothing.

So perhaps the best way is a $wpdb call, or a way to use WP_Query's meta_query on the post ID field?

Share Improve this question edited Aug 2, 2013 at 5:40 Drew Baker asked Aug 2, 2013 at 2:13 Drew BakerDrew Baker 3121 gold badge3 silver badges10 bronze badges 4
  • 2 Could you please explain the complicated reality? – s_ha_dum Commented Aug 2, 2013 at 3:13
  • Updated to explain why I don't want to use array_diff if possible. I think a $wpdb approach might be best. – Drew Baker Commented Aug 2, 2013 at 5:22
  • @DrewBaker I still do not understand a think. You say: I have many different arrays to compare against, and some of them are multidimensional But to use include and exclude you have to pass a flat array of ids. So do you do some logic to exctract two flat arrays from the different and multidimensional array? If so, you can actually run array_diff and if result is empty you can use an if and never run the query, $posts = ! empty($diff) ? get_posts($args) : array(); – gmazzap Commented Aug 2, 2013 at 9:40
  • OK, I hear what you guys are saying. I'll use array_diff(). Thanks! – Drew Baker Commented Aug 2, 2013 at 17:18
Add a comment  | 

2 Answers 2

Reset to default 5

post__in and post__not_in are mutually exclusive.

Note: you cannot combine post__in and post__not_in in the same query.

http://codex.wordpress/Class_Reference/WP_Query

As your question is written, the solution you reject-- that of using array_diff-- is the obvious answer.

If it is true that that solution won't work you will need a filter on posts_where (probably) that will provide the query logic you need. As you have not explained "the reality [that] is more complicated than this question" it is really not possible to offer a guess at what that logic might be.

But here is an example of a posts_where filter:

function smbd_cats_by_days ($where = '') {
    // global $days_limit; // if a variable
    // $days_limit = DAYS_LIMIT; // if a constant
    // $days_limit = get_option('days_limit',100);
    // you have to uncomment one of the above, 
    // depending on your choice of mechanisms
    $where .= " AND post_date < '" . date('y-m-d', strtotime("-{$days_limit} days")) . "'";
    return $where;
}
add_filter('posts_where', 'smbd_cats_by_days');

Based on the edit to the question and on this statement of intent:

I'm trying to only show posts that a user hasn't seen...

Write the PHP to create an array of posts that the user has seen and exclude them with post__not_in. Your attempt to shove everything into the query is only complicating things.

I also think it's easier for others to read if it's a WP_Query or $wpdb call, rather than lines and lines of PHP to end up with a query parameter.

By the time your write the filters and or SQL to include everything in the query it will not be more "readable" and it is questionable whether it would be more readable in the first place. You are trying to do this the hard way. WP_Query is not capable of complex logic and complex logic in SQl is hard to write and hard the read even on a good day.

Excude and include cannot be used together, this code is used in core, so or one or the other.

...
if ( ! empty($r['include']) ) {
  $incposts = wp_parse_id_list( $r['include'] );
  $r['posts_per_page'] = count($incposts);  // only the number of posts included
  $r['post__in'] = $incposts;
} elseif ( ! empty($r['exclude']) )
...

A $wpdb query is easy if the only arguments you need are only ones you posted.

This way is easy, but if you can't can explain why?

$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);
发布评论

评论列表(0)

  1. 暂无评论