Search code examples
phpwordpressmultisite

Using switch_to_blog in pre_get_posts hook


I have a multisite WordPress with two sites in it (two languages), and I'm developing a theme for both of them. I have a custom type (named 'lesson') that I want to have it shown in both of the sites. So I ended up using pre_get_posts hook to reach my purpose, but the problem is when I change the blog id in this action, the other actions (and filters) don't work anymore!

I chose to have two sites for translation because generally the contents of the sites are different, but there is some of data that should be in both of the sites. So, I decided to insert the 'lesson' data in only one of the sites and use the data in the second one.

So, I have (for example) this two urls:

example.com/en/lesson1
example.com/fr/lesson1

And I want to have the same data of both pages and the deference between them is the languages of the pages (except the post content that are the same).

So I used the 'pre_get_posts' hook to change the query before getting the data from db and make it fetch the data from the first site only:

function change_to_main_site_on_lesson( $query ){
    if( 'lesson' == $query->query['post_type'] && $query->is_main_query() && $query->is_single() ){
        switch_to_blog( 1 );
    }
}
add_action( 'pre_get_posts', 'change_to_main_site_on_lesson' );

And, boom! this works! Both urls are working in expected language! very good! But... There is a problem. The problem is that the code only changes the blog id to "1" and doesn't restore it to the current blog, and it has to be restored to the current block AFTER the query runs. So I decided to use another action to do that, and that action is 'get_posts', because it runs after the query runs. So I added this code to do that:

function return_to_currrent_site( $posts, $query ){
    restore_current_blog();
}
add_action( 'get_posts', 'return_to_current_site' );

After that I realized that this action (and the other actions and filters) dose not work at all! I found out that using switch_to_block() in the action using filter pre_get_posts makes the problem!

Any suggestions?


Solution

  • The code above has two mistakes:

    1. The correct hook to run after getting posts is not get_posts, It is the_posts.

    2. The hook the_posts is prepared to be used in a filter not an action.

    Changing these two mistakes solved my problem:

    function change_to_main_site_on_lesson( $query ){
        if( 'lesson' != $query->query['post_type'] || $query->is_admin ){
            return ;
        }
    
        switch_to_blog( 1 );
    }
    add_action( 'pre_get_posts', 'change_to_main_site_on_lesson' );
    
    function return_to_current_site( $posts, $query ){
        if( 'lesson' != $query->query['post_type'] || $query->is_admin ){
            return $posts;
        }
        restore_current_blog();
    
        return $posts;
    }
    add_filter( 'the_posts', 'return_to_current_site', 10 , 2 );