You need to use wp_reset_query()
instead of wp_reset_postdata()
when using WP_Query
. You only need to use wp_reset_postdata()
if you’ve used setup_postdata()
.
Also, this line isn’t quite right:
$post_id = $query->post->ID;
Since you’re inside a Loop, you can use:
$post_id = get_the_ID();
Thanks for those corrections!
My code is based on the sample from https://codex.wordpress.org/Class_Reference/WP_Query#Multiple_Loops. It does show using wp_reset_postdata().
The sample itself produces the same result which is what I find interesting.
After some digging I found that this is still an open bug:
https://core.trac.wordpress.org/ticket/18408#comment:14
I simply rewrote my loop so as not to use the reset function and it works fine:
function kl_display_error_nonperishable_highlighted_events(){
$post_id;
$perishablePosts = get_perishable_posts();
$query = new WP_Query(array('cat' => 4));
if ($query->have_posts()){
foreach ($query->get_posts() as $post){
$post_id = $post->ID;
if (!in_array($post_id,$perishablePosts)){
?>
<div class="notice notice-error"><p>A highlighted post is currently not set to expire. This post will not appear on the landing page. Click <a href="http://lions.kitterycoc.com/wp-admin/post.php?post=<?php echo $post_id; ?>&action=edit">here</a> to edit the post.</p></div>
<?
break;
}
}
}
}
Yup, whether you need to reset depends as much on what occurs afterwards as much as how the query was utilized to start with 🙂
I didn’t read through that Trac ticket to grasp what the underlying problem is, but it seems much of the problem is confusion over what to use when, more than there being an actual bug. Everyone should recognize the real difference between resetting post data and resetting the query. Aside from copying global $wp_the_query to global $wp_query, both functions do exactly the same thing. Check out the source code.
AFAIK the only place the global $wp_the_query is used is for the main query created internally from the request. The only function directly altering the main query is query_posts(), which no one should be using anyway. If that is indeed the case, we can pretty much only use wp_reset_postdata() anytime a reset is needed. Every query does not need to be reset. Whether to use wp_reset_postdata() or not is the only decision to make.
Yes, the issue is that both of those function cause the issue. This only happens on select back end pages. You cannot use any form of the_loop, posts have to be looped through manually because both of those functions mess with something in those pages.
If you try using either of those function in the admin notices on post.php or edit.php you will find the same side effects become apparent.
A solution was proposed however it also had side effects. No solution has been implemented because the issue is easy to work around and a best case solution has not been selected.