I have a multisite network of sites which should display blog content from each other if the blog post has a tag with the site name.

To gather all posts within the network I use the SWT (Sitewide Tags) plugin as it seems most efficient. I store all posts in the main site (blog id 1) and from my other sites I want to query the main sites posts table for posts containing a tag with the querying site’s domain name.

I have working code in a page template (home.php) – see below – but I understand the action pre_get_posts are the way to go, but I can’t seem to figure out how to change the table to query. Should I perhaps do a JOIN in the action posts_join?

If my solution seems to be way more complicated than it should be, feel free to bash me with other suggestions 🙂

This is my current template code:

$tags = array(
    'lundalogik-se'
);
switch_to_blog(1);
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$wp_query = new WP_Query(array(
    'post_status' => 'publish',
    'paged' => $paged,
    'orderby' => 'date',
    'order' => 'desc',
    'tag' => implode(",", $tags)
));

while (have_posts()) : the_post();
  [..]

How can I rewrite this in pre_get_posts?

Note; as you see the tag I’m searching for is static at the moment, this will change to match the domain name + ccTLD of the querying site or something similar later on.

Note 2; I’d rather not use switch_to_blog() since I read it’s expensive but haven’t found a best practice for querying other blogs inside a network. Should I set the table name to query manually instead?

I have read most posts both here, in blogs and in the Codex (WP_Query, pre_get_posts etc.) touching multisite querying but almost all talks of using switch_to_blog and restore_current_blog.

2 Answers
2

OK so for reference I ended up actually using switch_to_blog() and restore_current_blog(). I found no references whatever for querying multiple tables (except writing my own JOIN-statements) when followed the source code for the action pre_get_posts.

A lot of advice was given to skip restore_current_blog() to save CPU-cycles but when I checked the source code for this I saw that it would cause a huge memory problem since the main thing restore_current_blog() does is to pop the latest inserted object in a global array and this array would grow hugely with each switch_to_blog() that one does not do a restore_current_blog() on.

Please feel free to check the source code and also see @user42826’s answer regarding this at https://wordpress.stackexchange.com/a/123516/14820.

For those who are interested, I ended up with transients both for the site-list and for the result to save both CPU-cycles and DB performance. I only needed data to be updated if it were stale (15 minutes or more of age). Only relevant bit of function included below:

$site_transient = get_site_transient( 'multisite_site_list');
if ($site_transient == false || LL_USE_TRANSIENTS == false) {
    $using_site_transient = false;

    // no cache available
    global $wpdb;

    // TODO: get prefix for wp tables
    $site_list = $wpdb->get_results($wpdb->prepare('SELECT * FROM nw_blogs WHERE public = %d AND deleted = %d ORDER BY blog_id', 1, 0));

    // set transient
    set_site_transient('multisite_site_list', $site_list, LL_TRANSIENT_EXPIRES);

} else {
    //log_msg("SITELIST - Transient found, using cached query..");
    $site_list = $site_transient;
    $using_site_transient = true;
}

//log_msg("$id - get_posts_from_network | tags: " . implode(",", $tags) . " | tag_slug__and: $lang_full");

$start = microtime(true);

// get blogpost transient, if existing
$post_transient = get_site_transient( 'limelight_recent_posts_' . $hash);

// if not, do query and save result as a transient
if ($post_transient == false || LL_USE_TRANSIENTS == false) {
    $using_post_transient = false;
    $blogposts = array();

    foreach ($site_list as $site) {
        switch_to_blog($site->blog_id);
        $posts = get_posts(array(
            'post_status' => 'publish',
            'orderby' => 'date',
            'order' => 'desc',
            'tag' => implode(",", $tags),
            'tag_slug__and' => array($lang_full)
        ));

        //log_msg("$id - get_posts_form_network | at site: $site->blog_id");

        foreach ($posts as $post) {

            //log_msg("$id - get_posts_form_network | at site: $site->blog_id | got post!");

            $post->human_post_date = human_time_diff(get_post_time('U', false, $post->ID), current_time('timestamp')) . ' ' . __('ago', 'limelight');

            if (isset($tagline_metabox)) {
                $meta = get_post_meta($post->ID, $tagline_metabox->get_the_id(), TRUE);
                $post->tagline = $meta['tagline_text'];
            }

            if (!isset($post->tagline) || $post->tagline == '')
                $post->tagline = substr($post->post_title, 0, 20) . '..';

            $post->post_date_timestamp = strtotime($post->post_date);           

            //$post->blog_id = $site->blog_id;
            $post->blog_name = get_bloginfo('name');
            $post->blog_url = get_bloginfo('wpurl');
            $post->permalink = get_permalink($post->ID);
            $post->author_name = get_userdata($post->post_author)->display_name;
            //$data = get_userdata($post->post_author);

            $blogposts[] = $post;
        }
        restore_current_blog();
    }

    // sort blogposts by post_date_timestamp, descending
    array_sort_by_obj($blogposts, 'post_date_timestamp', SORT_DESC);

    // pick five latest posts
    if (sizeof($blogposts) > 5) {
        $posts = array();
        for ($i = 0; $i <= 4; $i++) {
            $posts[$i] = $blogposts[$i];
        }
        $blogposts = $posts;
    }

    // set transient
    if (LL_USE_TRANSIENTS)
        set_site_transient('limelight_recent_posts_' . $hash, $blogposts, LL_TRANSIENT_EXPIRES);

Leave a Reply

Your email address will not be published. Required fields are marked *