11

I am trying to understand when and why I should use the global $post variable. I have tried to do the following on a post page, outside the loop, and as expected it works.

    <?php 
        global $post;
        echo $post->ID;
    ?>

If I do the same on an archive page (just wanted to see what happens), for some reason it also works, retrieving the ID of the previous post, even if I deleted the code above from the previous post page. Is this like some kind of caching? How does this work exactly?

I understand global $post can be useful if I'm working on a fuction in functions.php. Is this the only use case?

Many thanks

2 Answers 2

20

This is perhaps too broad a question to answer well. The $post global could be used in all sorts of ways. Whether or not it should be used depends on each circumstance.

However, as I understand it, the main intended purpose of the $post global is its use in theme template files.

When you use the_title() or the_content() or the_author() or any of the very many template functions, WordPress goes looking for this information in the $post global. As a general rule, when working in the template files, you will always want to use these template functions, like get_the_ID(), instead of accessing $post->ID directly.

So if you want to understand the $post global better, you should read up on how The Loop works in WordPress, particularly within the template files. When a Loop runs the_post(), it is setting up the global with the current item.

In template files, you'll usually be iterating over a Loop for a query that is run automatically. When you access a single Page, for instance, WordPress knows to run a query for that page and load the page.php template.

If you want to retrieve extra posts outside of the main Loop, for instance in your functions.php, you would run your own WP_Query, initiate the Loop and then use the template functions. Only access the $post global directly if you're unable to access the information you want through an existing function.

When you're done looping over your own WP_Query, you'll find that the $post global is now stuck on your custom query. So, for instance, on our single page template, after our custom loop, we may no longer have the current page set up in $post. You can restore the $post global to its former state with wp_reset_query. This is absolutely critical or else you can break other plugins or themes which expect the original $post global.

2
  • Thans for taking the time of answering me, not it's a bit clearer to me - basically I have to use it in functions only, because I generally am inside a default loop or a custom query.
    – akmur
    Dec 5, 2014 at 12:32
  • 1
    Thank you for the articulate answer as this has been very helpful and will continue to be. The most notable information I needed was "Only access the $post global directly if you're unable to access the information you want through an existing function."
    – Radmation
    Apr 6, 2021 at 17:33
5

I have done a post or two on this that might have been lacking some info as this question tackles some other issues. I have also asked a question which you can check here with a great answer from @G.M.

Basically, the $post global is set by $wp_query->the_post() and is accessible throughout the template, not just inside the loop. This is why they are called globals

Here is the current source

3681        public function the_post() {
3682                global $post;
3683                $this->in_the_loop = true;
3684
3685                if ( $this->current_post == -1 ) // loop has just started
3686                        /**
3687                         * Fires once the loop is started.
3688                         *
3689                         * @since 2.0.0
3690                         *
3691                         * @param WP_Query &$this The WP_Query instance (passed by reference).
3692                         */
3693                        do_action_ref_array( 'loop_start', array( &$this ) );
3694
3695                $post = $this->next_post();
3696                setup_postdata($post);
3697        }
3698

From this you also get the answer to your question on why you get the last post as the $post in the archive page (and for that matter, any page). $post is always effectively set to the last post in the returned $posts array via $wp_query->next_post()

You have to be very careful making use of this global outside the loop as custom queries and some functions can access it and change its value as described in the linked post. That is one reason why you should always reset the postdata from a new instance of WP_Query. query_posts also breaks this global as it breaks the main query, one reason why query_posts should be avoided at all costs

You basically just need to define the global $post in a function as this is outside the current template, but you can define the global outside the loop if you wish.

To conclude, as the $post global is one of the most unreliable globals which can be very easily being modified by functions, I would suggest using the recommendations by @G.M. In the linked question

1
  • Thanks, good answer, I'm not sure which one to choose as correct, they're equally good
    – akmur
    Dec 5, 2014 at 14:15

Your Answer

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

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