Are you having trouble with wp_reset_postdata not working like it should?
If you’re trying to reset post data on an admin page, you may not be experiencing a simple case of programmer error. There’s a known bug in WordPress (that’s been around for SEVEN years, believe it or not) related to wp_reset_postdata on admin edit pages.
Read on to find out if this bug is affecting you, and if so, how to get around it.
Known wp_reset_postdata bug on admin pages
To put it simply, there’s a known bug in WordPress core that means wp_reset_postdata doesn’t work as it should on admin edit pages.
A tiny note exists on the WP_Query class reference, but if you happen to miss that—I did when I stumbled on the bug myself—you could potentially spend hours wondering what the heck you’re doing wrong.
Don’t hold your breath for a quick fix, either: the bug was first reported in 2011 and the last progress you can see on the ticket was from over a year ago, so it may not be getting fixed any time soon. It’s not a huge bug, so the WordPress team have bigger fish to fry.
There’s a lot more detail on the specifics of the problem on Trac ticket #18408. Some of the most informative comments are:
While using an explicit WP_Query object in a meta box, you cannot reset the postdata after the loop, no matter what you try. Any subsequent meta boxes identify global $post as the last post of the custom query.
— @misternify, https://core.trac.wordpress.org/ticket/18408#comment:9
The root issue is that wp_reset_postdata() is designed to reset globals to match the main query. But in the case of post.php, there is no main query – the $post global is populated manually, using get_post(), rather than through the normal $wp_query loop.
— @boonebgorges, https://core.trac.wordpress.org/ticket/18408#comment:14
How to get around the wp_reset_postdata admin bug
There are a handful of different solutions suggested in the Trac ticket’s discussion. The one you ultimately choose is down to programmer preference, but here’s how I decided to proceed:
The solution I used in EBB was suggested by @jpSimkins in https://core.trac.wordpress.org/ticket/18408#comment:25:
To bypass this issue, do not use the_post as this is the issue.
So, after you issue your query and start to loop through the results, do not use $query->the_post() to set up post data. As @jpSimkins notes in his comment, you won’t be able to use template tags like get_the_title() without arguments, but you can still access that information in other ways.
Here’s the relevant code snippet from EBB for your reference:
$args = array( 'post_type' => EBB_Optin_CPT::POST_TYPE_SLUG, 'post_status' => 'publish', 'posts_per_page' => -1, 'order_by' => 'title', 'order' => 'ASC' ); $optin_query = new WP_Query( $args ); if ( $optin_query->have_posts() ) { $results = array(); // Non-standard loop due to ongoing bug in core: https://core.trac.wordpress.org/ticket/18408 // Can't wp_reset_postdata on post.php edit screen foreach ( $optin_query->get_posts() as $p ) : $results[] = array( 'id' => $p->ID, 'title' => get_the_title( $p ) ); endforeach; }
According to the discussion on the Trac ticket, you can also use get_posts without encountering the bug (as long as you don’t setup_postdata in your results processing).
Have you been affected by the dreaded wp_reset_postdata bug? Feel free to moan about how much time you wasted looking for the problem in the comments below. ?
