0

Assume all the code below is in a theme's function.php

If I add get_post() at the top, It'd get null, which is totally expected since I'm not in the loop, or nothing has been done.

But I add

add_filter('template_include', 'call_get_post'));

function call_get_posT(){
 var_dump(get_post())
}

Then I'll get the info for the latest post.

I tried this in a fresh install of WP locally so I'd assume this is expected behavior, but I don't understand it. I'm not in the loop, and I haven't called anything to start a query, why would get_post() return the first post? Same result if I use global $post.

Can someone explain what's going on here?

2 Answers 2

2

I tried this in a fresh install of WP locally so I'd assume this is expected behavior, but I don't understand it. I'm not in the loop,

No but that doesn't mean a main query doesn't exist, it just means your code to display it hasn't run yet

and I haven't called anything to start a query,

But the main query has started and completed, it needs to in order for conditionals used to decide which template to load to work.

why would get_post() return the first post? Same result if I use global $post.

Why wouldn't it? Note that you get the same result because they are literally the same thing.

When you load a URL several things happen:

  • the pretty URL gets matched against a rule that turns it into an ugly URL aka index.php?foo=bar
  • those URL parameters get whitelisted and fed into the main query WP_Query, which is what the main loop functions operate on.
  • that query is used to power functions like is_single or is_archive etc
  • WP uses those functions to make a decision about which theme template or block template to load.

So the main query has already fetched the posts, and the first post is already available. If it wasn't, there'd be no way to catch 404s or load page templates for pages.

Ofcourse, you've not called the_post() yet which might be why there's some confusion, but that makes more sense if you know these things:

  • if you don't tell get_post which post to get, it defaults to the current post, aka global $post. It's the very first thing it does in the function
    • if you call this too early it can return null
  • In the main WP class there's a function named register_globals that sets up initial values for major globals, including $post, which at the time of writing has a line that looks like this: $GLOBALS['post'] = isset( $wp_query->post ) ? $wp_query->post : null;
    • it too will set it to null if no posts were found to avoid problems

Remember, all frontend pages have a main query, even if you use get_posts or new WP_Query in your templates.

2
  • That's a fantastic answer, thank you! Is there a way to differentiate if the $post is coming from the initialized query or if the request is actually for that post? Commented Aug 11, 2022 at 18:22
  • I'm not sure what you mean, can you give an example of when those two situations might not be the same?
    – Tom J Nowell
    Commented Aug 11, 2022 at 18:55
0

WordPress queries the correct posts from the database automatically on every page load based on the URL. It needs to do that to know which template to load. Part of this process involves initialising the global $post variable to the first post found (or last, I can’t remember right now which one it will be). On single posts this will be the only post.

You don’t need to initiate any query yourself for WordPress to query posts. If fact, if you're manually querying posts for the main list of posts on your blog page (or category archive etc.) you're doing it wrong. The purpose of the standard loop is to simply loop through those posts so that they can be displayed.

1
  • this is crazy counter intuitive, and I couldn't find this explanation nowhere in the docs (prob didn't read the correct ones but anyway). Thanks. Commented Aug 11, 2022 at 17:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.