Network_Query usage - the query returns no posts

I have a template pagetag.php, which should basically display all posts and pages (I use Tag Pages plugin to add tags to pages, not only to posts - http://wordpress.org/plugins/tag-pages/) marked with a certain tag across the entire multisite server. It works properly when I use WP_Query to retrieve all posts from the current site. It would seem logical that by replacing WP_Query by Network_Query I'd retrieve all posts from all sites. However when I use Network_Query, the query returns only two entries, both of which are duplicates of the page I'm currently viewing, which isn't even marked by any tag. Is it possible to use Network_Query to accomplish this task, and if yes then how to use it and what am I doing wrong?

Here is the relevant piece of code of pagetag.php, somewhat simplified for clarity. The variable $tag holds the tag to display. This piece works correctly for displaying posts from current site:

<?php
if ($tag) {
$args = array(
'tag' => $tag,
'posts_per_page' => 11
);
// The Query
$query = new WP_Query( $args );
while ($query->have_posts()) : $query->the_post(); ?>
<div class="col-sm-4 tile">
<?php get_template_part('templates/content', get_post_format()); ?>
</div>
<?php endwhile; ?>

And below is the Network_Query version, which returns wrong posts:

<?php
if ($tag) {
$args = array(
'tag' => $tag,
'posts_per_page' => 11
);
// The Query
$query = new Network_Query( $args );
while ($query->have_posts()) : $query->the_post(); ?>
<div class="col-sm-4 tile">
<?php get_template_part('templates/content', get_post_format()); ?>
</div>
<?php endwhile; ?>

  • Koliber

    I've modified the query and subsequent loop as follows:

    <?php
    if ($tag) {
      $args = array(
        'tag' => $tag,
        'posts_per_page'  => 11
      );
    
    // The Query
    network_query_posts($args);
    
    while (network_have_posts()) :
    	network_the_post();
    ?>
        <div class="col-sm-4 tile">
          <?php
    		 // global $network_post;
    		  get_template_part('templates/content', get_post_format($network_post));
    	  ?>
        </div>
    <?php endwhile; ?>
    
    <?php network_reset_postdata(); ?>

    But still I'm getting only those two posts, even though there are four posts marked with the tag on the site alone, and more on the whole server. It seems that either network_query_posts() searches for the wrong posts, or network_the_post() sets up wrong $network_post.

  • Koliber

    I've also tried replacing the global vars with $query fields, so that I can use get_post_format() on an arbitrary post. This works perfectly (though for a single site only):

    $query = new WP_Query( $args );
    
    while ($query->have_posts()) :
    	$query->the_post();
    ?>
        <div class="col-sm-4 tile">
          <?php get_template_part('templates/content', get_post_format($query->post->ID)); ?>
        </div>
    <?php endwhile; ?>
    
    <?php if ($query->max_num_pages > 1) : ?>
      <nav class="post-nav">
        <ul class="pager">
          <li class="previous"><?php next_posts_link(__('? Older posts', 'roots')); ?></li>
          <li class="next"><?php previous_posts_link(__('Newer posts ?', 'roots')); ?></li>
        </ul>
      </nav>
    
    <?php endif; ?>
    <?php } ?>
    <?php wp_reset_postdata(); ?>

    And this, with lines 1 and 21 altered, doesn't:

    $query = new Network_Query( $args );
    
    while ($query->have_posts()) :
    	$query->the_post();
    ?>
        <div class="col-sm-4 tile">
          <?php get_template_part('templates/content', get_post_format($query->post->ID)); ?>
        </div>
    <?php endwhile; ?>
    
    <?php if ($query->max_num_pages > 1) : ?>
      <nav class="post-nav">
        <ul class="pager">
          <li class="previous"><?php next_posts_link(__('? Older posts', 'roots')); ?></li>
          <li class="next"><?php previous_posts_link(__('Newer posts ?', 'roots')); ?></li>
        </ul>
      </nav>
    
    <?php endif; ?>
    <?php } ?>
    <?php network_reset_postdata(); ?>
  • Koliber

    I've noticed yet another quirk. I've used Ashok's method, and it worked. However, I wanted to have more control over the order of posts, so I thought of adding them to an array first, then sorting the array according to some rule, and finally showing them using foreach(). It basically works like this:

    $found_pages = array();
    
    foreach ($blog_list as $blog) {
        switch_to_blog($blog['blog_id']);
    
        $query = new WP_Query( $args );
    
        while ($query->have_posts()) {
            array_push($found_pages, $query->the_post());
        }
        restore_current_blog();
    }
    
    // at this point we can sort $found_posts if we want to
    
    $i=0;
    
    foreach($found_pages as $found_page) : $i++;
        ?>
        <?php if( $i > 1 ) : ?>
        <div class="col-sm-4 tile">
        <?php else: ?>
        <div class="col-sm-8 tile">
        <?php endif; ?>
          <?php get_template_part('templates/content', get_post_format($found_page)); ?>
        </div>
        <?php
        endforeach;
    ?>

    When I use array_push($found_pages, $query->the_post()); to fill the array, I get a list of several copies of the first page found by the query. When I use array_push($found_pages, $query->next_post()); to fill the array, I get a list of several copies of the page I'm currently viewing. In both cases the number of pages found is right, but the pages themselves are wrong. So $query->the_post() and $query->next_post() return different results, and in both cases these results are wrong. I've also tried populating $found_pages array via $query->get_posts() (see below), and it also yields wrong posts.

    $new_posts = $query->get_posts();
    
    foreach($new_posts as $new_post)
        array_push($found_pages, $new_post);

    What am I doing wrong and what is the way to do it properly?

  • Ash

    $query->the_post() doesn't return anything, it just creates object in the background so you can use template function like the_post or the_title etc.

    What you can do is to pass the blog id and post id in an array so that after sorting you can fetch post by id and blog id.

    Like:

    $found_pages = array();
    $found_pages['blog'] = $found_pages['post'] = array();
    
    foreach ($blog_list as $blog) {
        switch_to_blog($blog['blog_id']);
    
        $query = new WP_Query( $args );
    
        while ($query->have_posts()) {
            $query->the_post()
            array_push($found_pages['blog'], $blog['blog_id']);
            array_push($found_pages['post'], get_the_ID());
        }
        restore_current_blog();
    }

    Otherwise you can insert all post title, content etc in a multi dimensional array.

    Hope it helps Please feel free to ask more question if you have.

    Cheers
    Ash