I have the following code and while get_the_ID() works, $post->ID does not, why?
$the_query = new WP_Query( array(
'post_type' => 'custompost',
) );
while ( $the_query->have_posts() ) : $the_query->the_post();
echo $post->ID;
endwhile;
Your WP_Query loop is incomplete. Your not checking if any posts were actually found before looping, nor are you presenting a message to show none were found, nor are you cleaning up afterwards. You’re also using the ‘other’ syntax that breaks brace matching in IDEs, making your life harder.
Try adding
global $post;
like this:When writing queries it’s important to be consistent and to get things right. So I recommend reading these slides by Andrew Nacin, a WordPress Core developer at Auttomatic:
http://www.slideshare.net/andrewnacin/you-dont-know-query-wordcamp-netherlands-2012
This will tell you where each type of query is appropriate, how they should be used, and why.
In the code above, I added an if statement to check if any posts were returned, and I added wp_reset_postdata which would allow you to continue using the main query by cleaning up after the custom loop.
The trick, as identified by Tom Nowell, is to add a reference to
global $post
.When you run
the_query->the_post()
, WordPress loads the first result of the query into a global$post
object. This is how it sets things up for all of the regular template tags:the_title()
the_content()
the_excerpt
()You see that we don’t pass anything in to these functions. We just call them. Each of these functions will internally reference the global
$post
object in order to parse, prepare, and print the desired output.Inside your loop, you call
the_post()
just fine to populate the data, but you don’t have a reference to the data itself within the scope of your loop. If you wanted to avoid referencing the global$post
object, you could instead useget_the_ID()
.Like the other template tags I’ve referenced above,
get_the_ID()
summons data from the global$post
object internally, so you don’t have to do it yourself.But if you do want to do this yourself, just add a global reference before you try to use
$post
:What is
wp_reset_postdata()
?If you’re building multiple loops, (i.e. you have a large post loop, but call some secondary loop inside of it), you can call
wp_reset_postdata()
to reset things.Basically,
the_post()
will set the global$post
object to have the data for the requested query.the_query->the_post()
will overwrite$post
with data fromthe_query
.wp_reset_postdata()
will reset$post
to the original query.So if you’re using nested or multiple loops,
wp_reset_postdata()
is a way to get back to the loop and$post
object you had available before you called your secondarythe_query->the_post()
.