Resetting $post in WordPress admin

I have run into a bug a few times in the past little while that had me stumped. When creating meta boxes on the admin side of WordPress that contained custom loops, I couldn’t reset $post using wp_reset_postdata() – it just didn’t work.

Originally, I thought maybe I was doing it wrong because I was using get_posts, so I tried WP_Query with the same results. So, thinking I had a legitimate bug, I went to report it and found that there was already a ticket and a patch for it ( gotta love the WordPress community ). The patch is a nice, elegant fix that worked well when I tested it – but until it’s accepted into core it’s not really an option to use because hacking core is bad. So I rolled my own in the meantime.

My solution

My approach was to create two new function that are similar to the ones we use now to setup and reset post data. I’d rather not introduce new items to the API but in this situation ( no hooks available and can’t edit core ) it was my only option.

The general approach is to store a copy of the original $post object before we change it with setup_postdata() and then retrieve it afterwards and reset $post accordingly.

In setup_admin_postdata we look for the existence of $GLOBALS[‘post_cache’] and use it to store $post. If this is the first iteration of the loop, thenĀ $GLOBALS[‘post_cache’] shouldn’t exist and we know that $post is original one for the page/post/cpt we’re currently editing.

We can only do this the first time as any subsequent calls to $post will give us the object setup with setup_postdata() and the data will be incorrect. The next part is the same as if we were using setup_postdata() normally in the loop. We set $post to the object we want to setup and then pass it to setup_postdata().

The wp_reset_admin_postdata retrieves the post object stored in $GLOBALS[‘post_cache’], passes it to setup_postdata(), then removes $GLOBALS[‘post_cache’]. This last part is important should there be more than one loop in play.

Here is an example of using it to create a meta box with a select menu:

I have not done a tone of testing for this but so far I haven’t seen any bugs popup. I’m not entirely sold on using $GLOBAL either but other storage options haven’t seemed to work so far.

Hopefully the proper patch gets committed to core and this won’t matter anyway, but in the meantime please let any comments or suggestions in the comments below.

 

Leave a Reply

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