Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

share|improve this question
    
This might be helpful: wordpress.stackexchange.com/questions/70129/… –  ialocin Oct 28 '13 at 12:06
    
@ialocin thanks I have already checked out that post and he seems to be a bit off, he allocated a $test_obj but never uses it and pre_get_posts doesn't return anything, it gets $query by reference and from what I can see he never attaches $test_obj to $query->something. Also, he's using switch_to_blog which I'd rather avoid if possible :). –  Johan Nordström Oct 28 '13 at 12:26
    
Did you ever get this working? I'm coming up against exactly the same situation now –  josh Mar 7 at 12:14
1  
@josh no, after checking the source code I found no way to do this with the action pre_get_posts so I resorted to switch_to_blog() and restore_current_blog(). Note: I found advice saying I should skip restore_current_blog() but analyzing the code for those two functions I could see that it builds up a huge array taking up lots of memory if I do not "pop" each switch_to_blog() with a restore_current_blog(). –  Johan Nordström Mar 7 at 16:17
    
@josh see my answer below for example code, reasoning and reference. –  Johan Nordström Mar 7 at 16:29
show 1 more comment

3 Answers

up vote 1 down vote accepted

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 http://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);
share|improve this answer
add comment

Try the following:

add_filter( 'pre_get_posts', 'get_post_from_main_blog' );
function get_post_from_main_blog($query) {
    global $wpdb;
    $wpdb->posts = 'wp_posts';
    return $query;
}

You may need to change wp_posts to your main blog's post table name.

share|improve this answer
    
That does not explain how to query other sites within the same Wordpress network, which was my question. –  Johan Nordström Mar 20 at 8:23
add comment

Usefull:

Using pre_get_posts in WordPress.

http://devotepress.com/wordpress-coding/when-to-use-pre_get_posts-in-wordpress/#.Us9KyNIW0rg

share|improve this answer
    
answers should answer the original question within its content and be more than links to external sites. –  Milo Jan 10 at 1:28
    
Copy / paste all content is not a good idea right? See, there is write a Usefull and if you has check the link, then you see a lot of functions that can be usefull for this topic. –  Foxsk8 Jan 10 at 1:34
    
regardless of its usefulness, it does not answer the question. and answers consisting entirely of external links are discouraged because if the site were to disappear, your link becomes useless. see how to answer for more info. –  Milo Jan 10 at 1:58
    
Thanks @Foxsk8 but unfortunately it doesn't say anything about querying other sites in a multisite network :/ –  Johan Nordström Jan 10 at 8:42
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.