Question

I realize there have been a few questions which dance around the solution I am after but I believe I am looking for something specific.

This is actually a two part question:

1) My goal is to have wordpress operate in network (multi-site) mode and I am trying to figure out a way to essentially "group" specific sites together. I am aware of the "Multi-Network" plugin but I question if this is the best approach for this? The key here is to allow specific users to add/edit the sites within their own sub-network.

2) This is the key question of this post... I would like to know the best approach which would allow me to essentially query posts from within this "sub-network" of sites. So, for example if there are 10 sites within this sub-network and each of them created posts within a custom post type called "news" then I would like the ability to display for example the 10 most recently published posts from this collection of 10 sites.

NOTE: I need the ability of being of being able to create multiply sub-networks which in turn means that a query of the latest published "news" can only display posts from those belonging to the correct group.

Finally - I do realize solutions exist for doing stuff like this but I am looking for the best approach on both cases which require the LEAST amount of database load/queries. I would also very much like to do this through code in my functions.php file rather than installing plugins which create extra bloat.

I am very open to any suggestions and appreciate any response.

Was it helpful?

Solution

I know you said you'd rather not install a plug-in, but that's exactly what you want to do in this situation. Placing the code in your theme's functions.php file requires you to either use the same theme across all sites in the sub-network or maintain multiple copies of the same file. On the other hand, you can create a simple plug-in for the network to encapsulate the functionality, then activate it on the network, and immediately have the functionality available with only one file to maintain. This would actually create less bloat than depending on your functions.php files.

The thing to keep in mind here is that you're either going to need to loop through each site on the network to find your posts or perform a custom query. I'd opt for the second routine because, though it's a bit more complicated, it's a single query rather than a different query for each blog.

Basically ... you'll need to do the following:

  1. Get a list of all the blog IDs in the network/sub-network. If using a vanilla installation, this can be found in the wp_blogs table. Just do a simple SELECT query to load up an array, then you can loop through to add each blog to your main query.
  2. Create a loop that adds each blog to a large query. You'll need to be JOINing tables together and searching based on blog_id (from wp_blogs), post_id (from wp_BLOG_posts), and the custom taxonomy.

Like I said, it's not a simple solution (the SQL statement will be very complicated and I don't have time to hack through it at the moment), but it will be a single statement that does all the work.

Alternatively ...

  1. Get a list of the blog IDs and store it in an array.
  2. Iterate through your array querying each blog in the network and appending your matches (posts with a certain taxonomy term) to a separate array.

With the alternative method you'll have to run a separate query for every blog in the network. If your network is 10-20 sites this isn't too much of an issue. If your network is 200-500 sites expect some performance issues to start cropping up.

Also, you should cache the results of your query if at all possible. If it's being run on multiple page loads (i.e. for a sidebar widget shared across the network) then you only want to run the query when there's new data to get. Otherwise, serve up the cached results so you don't slow down the network.

OTHER TIPS

I had a similar problem. I needed to get a list of posts across all network sites sorted by comments (to show the most popular posts). This is the function that I used.

The basis is that it first gets a list of all the blog ids in your network. It then builds a big single query (using UNION to combine all of the rows and not requiring ugly JOINs) that gets a result containing the columns blog_id, ID, and comment_count. Using that, I then use get_blog_post() to get each of the posts detailed information.

There are some debug lines that you can use at different points to see what's happening.

function txx_top_posts_mu( $howMany = 10 ) {
global $wpdb;
global $table_prefix;

// get an array of the table names that our posts will be in
// we do this by first getting all of our blog ids and then forming the name of the 
// table and putting it into an array
$rows = $wpdb->get_results( "SELECT blog_id from $wpdb->blogs WHERE
    public = '1' AND archived = '0' AND mature = '0' AND spam = '0' AND deleted = '0';" );
if ( $rows ) :
    $blogPostTableNames = array();
    foreach ( $rows as $row ) :
        $blogPostTableNames[$row->blog_id] = $wpdb->get_blog_prefix( $row->blog_id ) . 'posts';
    endforeach;
    //print_r($blogPostTableNames);

    // now we need to do a query to get all the posts from all our blogs
    // ordered by the number of comments and with limits applied
    if ( count( $blogPostTableNames ) > 0 ) :
        $query = '';
        $i = 0;
        foreach ( $blogPostTableNames as $blogId => $tableName ) :
            if ( $i > 0 ) :
                $query.= ' UNION ';
            endif;
            $query.= " SELECT ID, comment_count, $blogId as `blog_id` FROM $tableName ";
            $i++;
        endforeach;
        $query.= " ORDER BY comment_count DESC LIMIT 0,$howMany;";
        //echo $query;
        $rows = $wpdb->get_results( $query );

        // now we need to get each of our posts into an array and return them
        if ( $rows ) :
            $posts = array();
            foreach ( $rows as $row ) :
                $posts[] = get_blog_post( $row->blog_id, $row->ID );
            endforeach;
            //print_r($posts);
            return $posts;
        endif;
    endif;
endif;
return false;

}

You definitely need a multisite network plugins. There's three to choose from currently: two paid, one free.

From there, you can use something like the sitewide tags plugin to pull post to the main blog in each network.

Neither of these could be (or should be) done from a theme's functions file.

build a custom google search engine google.com/cse specify all the sites you want to search

embed it in your website

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top