Is it possible to query posts with tax queries after multisite switch_to_blog() function?

The question:

On my newly installed multisite with 1 installed plugin ACF. And all code below is not being run though any filter or action and on the front end.

On the front end in the page.php template, I can successfully tax_query posts directly from the current $site-purchase blog.

See code below and returned dumps for get_posts() and WP_Query.

// supplier args
$args = [
    'numberposts'   => -1,
    'post_type'     => 'purchase-supplier',
    'orderby'       => 'title',
    'order'         => 'ASC',
    'tax_query'     => [
        [
            'taxonomy'  => 'supplier-type',
            'field'     => 'slug',
            'terms'     => 'data-packaging'
        ]
    ]
];

// get supplier posts
$suppliers = get_posts($args);
// $suppliers = WP_Query($args);

dump($suppliers);

See get_posts($args) results below, which is outputting the correct expected result, post_id 14 (which has data-packaging term assigned to it)

Array
(
    [0] => WP_Post Object
        (
            [ID] => 14
            [post_author] => 1
            [post_date] => 2021-03-25 17:17:12
            [post_date_gmt] => 2021-03-25 17:17:12
            [post_content] =>
            [post_title] => Another company
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => another-company
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2021-05-26 20:31:25
            [post_modified_gmt] => 2021-05-26 20:31:25
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://localhost/purchase/?post_type=purchase-supplier&p=14
            [menu_order] => 0
            [post_type] => purchase-supplier
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

)

And here is new WP_Query($args) output…

https://gist.github.com/joshmoto/18976d06ce375570fd14ad55d326c9dd


However, if I use the exact same code above on $site_data blog in the page.php template. Using the multisite switch_to_blog($id) function to switch too $site_purchase to get the data…

// switch to purchase blog
switch_to_blog($site_purchase);

// supplier args
$args = [
    'numberposts'   => -1,
    'post_type'     => 'purchase-supplier',
    'orderby'       => 'title',
    'order'         => 'ASC',
    'tax_query'     => [
        [
            'taxonomy'  => 'supplier-type',
            'field'     => 'slug',
            'terms'     => 'data-packaging'
        ]
    ]
];

// get supplier posts
$suppliers = get_posts($args);
// $suppliers = WP_Query($args);

dump($suppliers);

// switch back to data blog
switch_to_blog($site_data);

Returns empty array via get_posts($args)

Array
(
)

And here is the new WP_Query($args) returned output…

https://gist.github.com/joshmoto/42bb619ca289fcbe4ea4e969fe42a1b0


But if I modify the php snippet query above used on $site_data blog in the page.php template. Simply by removing the tax_query key value…

// switch to purchase blog
switch_to_blog($site_purchase);

// supplier args
$args = [
    'numberposts'   => -1,
    'post_type'     => 'purchase-supplier',
    'orderby'       => 'title',
    'order'         => 'ASC',
//    'tax_query'     => [
//       [
//            'taxonomy'  => 'supplier-type',
//            'field'     => 'slug',
//            'terms'     => 'data-packaging'
//        ]
//    ]
];

// get supplier posts
$suppliers = get_posts($args);
// $suppliers = WP_Query($args);

dump($suppliers);

// switch back to data blog
switch_to_blog($site_data);

The get_posts($args) returns expected results. All posts from purchase-supplier are outputted in array…

Array
(
    [0] => WP_Post Object
        (
            [ID] => 14
            [post_author] => 1
            [post_date] => 2021-03-25 17:17:12
            [post_date_gmt] => 2021-03-25 17:17:12
            [post_content] =>
            [post_title] => Another company
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => another-company
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2021-05-26 20:31:25
            [post_modified_gmt] => 2021-05-26 20:31:25
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://localhost/purchase/?post_type=purchase-supplier&p=14
            [menu_order] => 0
            [post_type] => purchase-supplier
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

    [1] => WP_Post Object
        (
            [ID] => 131
            [post_author] => 1
            [post_date] => 2021-05-20 21:15:56
            [post_date_gmt] => 2021-05-20 21:15:56
            [post_content] => 
            [post_title] => Barry Callebaut
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => barry-callebaut
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2021-05-25 23:12:05
            [post_modified_gmt] => 2021-05-25 23:12:05
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://localhost/purchase/?post_type=purchase-supplier&p=131
            [menu_order] => 0
            [post_type] => purchase-supplier
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

    [2] => WP_Post Object
        (
            [ID] => 12
            [post_author] => 1
            [post_date] => 2021-03-20 22:53:51
            [post_date_gmt] => 2021-03-20 22:53:51
            [post_content] => 
            [post_title] => Hancock Cash & Carry Ltd
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => hancock-cash-carry-ltd
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2021-05-26 14:54:08
            [post_modified_gmt] => 2021-05-26 14:54:08
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://localhost/purchase/?post_type=supplier&p=12
            [menu_order] => 0
            [post_type] => purchase-supplier
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

    [3] => WP_Post Object
        (
            [ID] => 13
            [post_author] => 1
            [post_date] => 2021-03-25 16:53:18
            [post_date_gmt] => 2021-03-25 16:53:18
            [post_content] => 
            [post_title] => Test
            [post_excerpt] => 
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] => 
            [post_name] => test
            [to_ping] => 
            [pinged] => 
            [post_modified] => 2021-05-25 23:12:14
            [post_modified_gmt] => 2021-05-25 23:12:14
            [post_content_filtered] => 
            [post_parent] => 0
            [guid] => http://localhost/purchase/?post_type=purchase-supplier&p=13
            [menu_order] => 0
            [post_type] => purchase-supplier
            [post_mime_type] => 
            [comment_count] => 0
            [filter] => raw
        )

)

And here is the new WP_Query($args) returned output on $site-data without tax_query

https://gist.github.com/joshmoto/6df8c87f789564d64892b675c8a18a7f


Just cant get my head round why tax_query is failing in the switch_to_blog() function when all other tests show tax_query works on current $site_purchase blog, and the basic query (without tax_query) also works fine returning all purchase-supplier posts from $site_purchase blog within $site_data blog.

But as soon as I add my tax_query to my query args on $site_data, no purchase-supplier posts (id 14) are returned. Only an empty array is returned. Weird!

Any ideas? Thanks so much.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Yes, it is possible, but you will need to register the taxonomy on both sites because switch_to_blog() does not register the taxonomy for you, it mainly only switches the database and yet, taxonomies are not stored in the database, only the terms in the taxonomies.

But you don’t have to register the taxonomy on page load.. (but yes, that’s the proper way to do it). Because as long as it is registered, then the tax_query will work. And here’s an example to register the supplier-type taxonomy right after you call switch_to_blog():

// switch to purchase blog
switch_to_blog($site_purchase);

// Register the taxonomy.
$taxonomy = 'supplier-type';
if ( ! taxonomy_exists( $taxonomy ) ) {
    register_taxonomy( $taxonomy, null, [] );
    // or call your custom function which registers the taxonomy using the proper args
}

// ... your code.

[Edit] I gave the above example because (in the comments) you said, “using conditional logic to check if site is site and then registering types/taxes” and also “the tax is only registered on the purchase site, not the data site“. So the above should work even if you conditionally registered the taxonomy.

Also, in response to “Querying custom post types might not actually require register_post_type to be envoked, but tax_queries might actually need to understand the taxonomy is registered“, yes that’s correct.

More specifically, the tax query class uses taxonomy_exists() when generating the SQL statement (JOIN and WHERE clauses) for the tax query’s clauses (see source on Trac), and when the specified taxonomy is not registered, then the WHERE clause will be 0 = 1 (as in WHERE 1=1 AND ( 0 = 1 ) AND tsp_2_posts.post_type = 'purchase-supplier' ...) just as you could see in the $suppliers->request value here. Hence, that explains the empty posts array or the “why tax_query is failing in the switch_to_blog() function“.

So make sure the taxonomies used in your tax queries are properly registered. And despite WP_Query doesn’t check if a post type exists (e.g. using post_type_exists()) when querying for posts in custom post types, if after switching to any site you need to get the post type object or data (e.g. using get_post_type_object()), then make sure the post type is registered correctly.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment