Get Recent Posts by Date in Multisite

Everything in explanation is about CDTuts

I’ve created a WordPress Network and I want is to get the recent posts from all of the selected subdomain blogs. I need to get the latest All organized by date and not organized by blog ID.

Read More

I don’t want to use switch_to_blog thus, using foreach, because I’m only looping posts within the next blogs I switch. I want to actually combine the posts and have them all organized by date. I’d figure you’d have to do this by querying mysql instead of using WP_Query. But I was hoping for a more native way of doing this. This is for the list of posts to be made at the bottom of the front page as you can see with timestamps that aren’t ascended or descended by the number greater or lesser.

I even tried doing something like this, but this wouldn’t work either. Sorting the post by Unix timestamp, to only realize that the posts are still being organized by switch_to_blog instead of a timely manner.

<?php           
    switch_to_blog(1);
    $main_posts = get_posts();
    switch_to_blog(2);
    $php_posts = get_posts();
    switch_to_blog(3);
    $wp_posts = get_posts();
    switch_to_blog(4);
    $mac_posts = get_posts();
    switch_to_blog(4);
    $psd_posts = get_posts();
    switch_to_blog(1);

    $posts = array_merge($main_posts, $php_posts, $wp_posts, $mac_posts, $psd_posts);
    usort($post, get_post_time);

    foreach($posts as $post){
    ?>
        <li class="thumb"><a href="<?php echo the_permalink(); ?>">
            <div class="site-name">
            </div>
            <div class="title">
                <?php echo the_title(); ?><br> <?php echo get_post_time(); ?>
            </div>
        </a></li>
    <?php }         
?>

I’ve also created a function where I can select the ID of the blog using switch_to_blog. This will only work on the tiles at the top of the front page. But I’m also trying to do the same for the latest posts at the bottom. I won’t be able to create an offset so that I can keep the tile design while maintaining the 6 latest posts.

This was based on a previous answer on StackExchange

function global_latest_post($LatestBlogNumber,$LatestPostNumber, $LatestThumbSize, $LatestThumbNumber) {
    $original_blog_id = get_current_blog_id();
    $bids = array($LatestBlogNumber);    

    foreach($bids as $bid) {
        switch_to_blog($bid);
        $tiles = new WP_Query('posts_per_page=1');
        while ($tiles->have_posts()) : $tiles->the_post(); ?>
            <a href="<?php echo the_permalink(); ?>" class="<?php echo $LatestThumbSize; ?> thumb-<?php echo $LatestThumbNumber; ?>">
                <p class="cover">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
                <p class="bold bottom">Read More &rarr;</p>
                <h1><?php echo $LatestPostNumber; ?>. <?php echo the_title(); ?> in <?php bloginfo('name'); ?></h1>
            </a>
        <?php           
        endwhile;
    }
    switch_to_blog( $original_blog_id ); //switched back to current blog
}

Related posts

3 comments

  1. Since wordpress multisite uses different tables for all blogs, it is very inefficient to get all recent articles of all blogs (content aggregation) on display time since you have to query all blogs, sort the articles by date and display the ammount you need.

    Plugins like WordPress Post Indexer (https://premium.wpmudev.org/project/post-indexer) additional write all posts into one central db table in the moment you insert or update them. From there, you can query them very efficiently.

    I used the mentioned plugin by myself – its worth to try.
    I’m not associated with the creator.

    There are some things to consider too: For example: if you want display custom post meta fields, you’ll have to use switch_to_blog.

  2. I realize this question is rather “old”, however, I’ve come up with a solution.

    It’s possible to retrieve posts from other blogs in the multisite network without the need of using switch_to_blog(); or restore_current_blog();.

    /**
     * This is an example of retrieving posts from multiple blogs in Multisite.
     *
     * @author Michael Ecklund
     * @author_url https://www.michaelbrentecklund.com
     *
     * @param array $user_args
     *
     * @return array|bool|null|object
     */
    function mbe_get_network_posts( Array $user_args = Array() ) {
    
        if ( ! is_multisite() ) {
            return false;
        }
    
        $default_args = array(
            'post_type'   => 'post',
            'post_status' => 'publish',
            'limit'       => absint( get_option( 'posts_per_page' ) ),
            'orderby'     => 'post_date',
            'order'       => 'DESC'
        );
    
        $args = wp_parse_args( $user_args, $default_args );
    
        $args['orderby'] = strtolower( $args['orderby'] );
        $args['order']   = strtoupper( $args['order'] );
    
        if ( ! in_array( $args['orderby'], array(
            'id',
            'post_title',
            'post_name',
            'post_date',
            'post_modified',
            'post_author',
            'blog_id'
        ) ) ) {
            return false;
        }
    
        if ( ! in_array( $args['order'], array(
            'ASC',
            'DESC'
        ) ) ) {
            return false;
        }
    
        global $wpdb;
    
        if ( ! $blog_ids = $wpdb->get_col( "SELECT DISTINCT blog_id FROM {$wpdb->blogs}" ) ) {
            return false;
        }
    
        $queries = array();
    
        $where = array(
            'post_type'   => $wpdb->prepare( "AND post_type = %s", $args['post_type'] ),
            'post_status' => $wpdb->prepare( "AND post_status = %s", $args['post_status'] ),
        );
    
        foreach ( $blog_ids as $blog_id ) {
    
            if ( $blog_id == 1 ) {
                $prefix = substr( $wpdb->base_prefix, 0, - 1 );
            } else {
                $prefix = $wpdb->base_prefix . $blog_id;
            }
    
            $queries[] = $wpdb->prepare(
                "
                ( 
                    SELECT *, {$blog_id} AS blog_id
                    FROM {$prefix}_posts
                    WHERE 1=1 " . join( " ", $where ) . "
                    ORDER BY {$args['orderby']}
                    {$args['order']}
                    LIMIT %d
                )
                ",
                absint( $args['limit'] )
            );
    
        }
    
        $query = join( "UNION", $queries ) . "ORDER BY {$args['orderby']} {$args['order']}";
    
        return $wpdb->get_results( $query );
    
    }
    

    I kept it short and to the point. However, you could expand on this, by allowing multiple Post Types or Post Statuses, etc.

    Currently, with this function above, you can control the Post Type, Post Status, and sort by:

    Sortable Options:

    • Post ID
    • Post Title
    • Post Slug
    • Post Publish Date
    • Post Modification Date
    • Post Author ID
    • Blog ID

    Look at the default arguments for a list of arguments to override to suite your specific needs.

    Just thought I’d share this as a possible solution for someone to use a base for any situation where you might need to retrieve posts network-wide.

    Also, you could modify it to return Post ID’s, instead of everything. Then, you could use the post ID’s in a new WP_Query(); for something more complex like Meta queries and/or Taxonomy queries, etc.

    Hope someone finds this useful.

  3. Check out my answer in Get posts from Network (Multisite) . My ‘Multisite Post Reader’ plugin (free, open source) grabs all posts from all subsites with options to limit count, date, etc.

    It probably is a bit ‘heavy’ (inefficient), as mentioned by @jjarolim , but perhaps the code will help you in your efforts.

Comments are closed.