Support » Fixing WordPress » widget loop: collect queried posts IDs in array to exclude these in main loop

  • Resolved okiedokeymc


    I am currently building a magazine theme and need a little help handling multiple loops. I need to somehow collect the queried posts post_IDs in the widget code in order to exclude these posts from the main loop.

    So on the front page (= blog page) the theme displays the following:

    • WIDGET 1: 3 featured posts (posts from category 123)
    • WIDGET 2: the 5 latest posts from category XY
    • WIDGET 2: the 5 latest posts from category ABC
    • the main loop

    Each post can have more than one category.
    The main loop is supposed to exclude those posts that already have been queried by WIDGET 1 and WIDGET 2.

    So in the WP Codex there is a paragraph about how to do this with multiple loops. The solution looks like this:

    For the custom loop

    <?php $my_query = new WP_Query( 'category_name=featured&posts_per_page=2' );
    while ( $my_query->have_posts() ) : $my_query->the_post();
    $do_not_duplicate[] = $post->ID; ?>

    For the main loop:

    <?php if ( have_posts() ) : while ( have_posts() ) : the_post();
    if ( in_array( $post->ID, $do_not_duplicate ) ) continue; ?>

    As you can see, I use the same widget more than once. This makes me think I can’t just go and use $do_not_duplicate[] = $post->ID; in my widget code because it’ll get overwritten, won’t it?

    How can I store the IDs of the posts that have already been queried by the widgets in a variable or an array to use them in my index.php file ?

    I’m glad if anyone could give his/her thoughts on this.

Viewing 6 replies - 1 through 6 (of 6 total)
  • Chad


    I don’t know if I’m completely clear on what you mean when you say you use the “same widget twice,” but you shouldn’t need to worry anything being overwritten.

    As long as the first two loops are adding to $do_not_duplicate, and the third is not, then the posts from the first two will get excluded from your main loop.

    thanks for your reply.

    I tried to say that I placed WIDGET 2 twice in my widget area. The two widgets display the five latest post from the category I can set in the widget settings.

    WIDGET 1 does almost the same, only with three posts_per_page and a different layout.

    Anyway. I tried the approach from the Codex and it didn’t work which made me think maybe the $do_not_duplicate array gets overwritten by each instance of the widget.

    I must be doing it wrong because var_dumping the $do_not_duplicate variable returns NULL.

    If you want to review the code, here’s the link to pastebin with the relevant pieces:

    I changed
    $do_not_duplicate[] = $post->ID;
    $do_not_duplicate[] = get_the_ID();


    I forgot to place the empty array somewhere, so I put $do_not_duplicate = array(); in my functions.php file where I register the widgets.

    var_dumping it on index.php returns this:

    array(13) { [0]=> int(16406) [1]=> int(16383) [2]=> int(16372) [3]=> int(16462) [4]=> int(16403) [5]=> int(16389) [6]=> int(16039) [7]=> int(15815) [8]=> int(16440) [9]=> int(16336) [10]=> int(16330) [11]=> int(16322) [12]=> int(16318) }

    Unfortunately I’m not very good at PHP so excuse this stupid question: what am I going to do with this?



    $do_not_duplicate[] = $post->ID; will work if you declare global $post at the beginning of the function. That tells the function to look outside of itself for the $post variable.

    As far as your newly populated array, you should be good to go with

    <?php if ( have_posts() ) : while ( have_posts() ) : the_post();
    if ( in_array( $post->ID, $do_not_duplicate ) ) continue; ?>

    For your main loop, which will exclude the post ID’s listed in the array, but the problem is that if you use the second widget twice, the third widget’s posts are going to be added into the array as well.

    You said you only wanted the first two widgets excluded from the mail loop, is there any chance you can use a separate widget rather than reusing the second one?

    Alright Chad, thanks.
    Not only did I declare $post a global variable, I did this with $do_not_duplicate aswell, because I needed to use it in my custom widget code (functions.php) and on the blog page. This worked.

    There’s just one thing I consider a problem:
    if ( in_array( $post->ID, $do_not_duplicate ) ) continue;
    skips the posts, so the default posts_per_page you can set in the WordPress settings does not fit. Which means that if you have 6 posts to exclude and your blog pages show 10 posts by default, the main loop will display only 4 posts.

    This was originally not part of my question but if you or someone else has a hint – please don’t hesitate. Otherweise just ignore it 😉



    Hm. What if you change the query on the main loop to

    new WP_Query( array( post__not_in => $do_not_duplicate ) );

    That should pull all posts that aren’t listed in your array.

Viewing 6 replies - 1 through 6 (of 6 total)
  • The topic ‘widget loop: collect queried posts IDs in array to exclude these in main loop’ is closed to new replies.