using post__in allow duplicate post id

I have an array of ids in a specific order. I use post__in in my query to get posts from this array. I have some duplicate post IDs that I need to show twice in the page but the query seems to ignore them.
Let’s say the array is as follows

array values  = 1,2,3,4,2,5

When I pass this array to post__in, it doesn’t take value '2' twice as i specified in the array. Is there a workaround for this?

Related posts

Leave a Reply

2 comments

  1. The situation

    An array like array( 1,2,3,4,2,5 ) will be read like the following:

    Array(
         0 => 1
        ,1 => 2
        ,2 => 3
        ,3 => 4
        ,4 => 2
        ,5 => 5
    ) [length = 6 ]
    

    which seems ok. But when you look at the WP_Query object, you’ll see the following part added to the query string:

    " AND {$wpdb->posts}.ID IN ($post__in)"
    

    This means that each post will be fetched once.

    Conclusion

    So unless you don’t modify the query to include the post multiple times, you’ll be left with only an option to do this on runtime.

    Runtime configuration possibilities and x-raying the internals

    Every basic loop looks like this:

    if ( have_posts() )
    {
        while( have_posts )
        {
            the_post();
            // do stuff
        }
    }
    

    Now the global $post refers to what gets setup via the_post(). It basically is a wrapper for $GLOBALS['wp_query']->the_post();. And when you take a look at the WP_Query::the_post() method, you’ll find quite interesting things:

    function the_post() {
        global $post;
        $this->in_the_loop = true;
    
        if ( $this->current_post == -1 ) // loop has just started
            do_action_ref_array('loop_start', array(&$this));
    
        $post = $this->next_post();
        setup_postdata($post);
    }
    

    There you see $this->next_post(); called. And this one looks from the inside like the following:

    function next_post() {
    
        $this->current_post++;
    
        $this->post = $this->posts[$this->current_post];
        return $this->post;
    }
    

    Solution

    So you see that the main thing the loop relies on, is the current_post counter. This one is as well accessible from the front end/a template. Simply use

    $GLOBALS['wp_query']->current_post
    

    to “jump” between posts. So if you need to repeat a post after post X, then just check against it, switch for one round and then skip back.

  2. You can loop your ids and call get_post and setup_postdata :

    global $post;
    foreach ($ids as $id) :
        $post = get_post($id);
        setup_postdata( $post );
        the_title();
    endforeach;