Skip to main content
replaced http://wordpress.stackexchange.com/ with https://wordpress.stackexchange.com/
Source Link

As @tosho already explained in the linked postlinked post, $post === $GLOBALS['post'], so I will not go into that.

If this is a true page (created in the back end pages section), then you can use get_queried_object() to get the current page object. It is much more reliable than the $post global. You should take your time and read through this answer by @gmazzapthis answer by @gmazzap to my question heremy question here

As @tosho already explained in the linked post, $post === $GLOBALS['post'], so I will not go into that.

If this is a true page (created in the back end pages section), then you can use get_queried_object() to get the current page object. It is much more reliable than the $post global. You should take your time and read through this answer by @gmazzap to my question here

As @tosho already explained in the linked post, $post === $GLOBALS['post'], so I will not go into that.

If this is a true page (created in the back end pages section), then you can use get_queried_object() to get the current page object. It is much more reliable than the $post global. You should take your time and read through this answer by @gmazzap to my question here

added 1 character in body
Source Link
Pieter Goosen
  • 55.4k
  • 23
  • 115
  • 209

I like the idea that you would really want and are really looking at more reliable alternatives to $post AND get_queried_object(), that is quite evident from your comment. Your comment actually sparked something I was working on a while ago and completely forgot about, I think most of all, including me, are forgetting one very important global which is never modified (except by the filters and actions inside WP_Query itself*except by the filters and actions inside WP_Query itself), and that global is $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] holds the actual main query object. $GLOBALS['wp_query'] (AKA $wp_query) is only a copy of $GLOBALS['wp_the_query'].

I like the idea that you would really want and are really looking at more reliable alternatives to $post AND get_queried_object(), that is quite evident from your comment. Your comment actually sparked something I was working on a while ago and completely forgot about, I think most of all, including me, are forgetting one very important global which is never modified (except by the filters and actions inside WP_Query itself*), and that global is $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] holds the actual main query object. $GLOBALS['wp_query'] (AKA $wp_query) is only a copy of $GLOBALS['wp_the_query'].

I like the idea that you would really want and are really looking at more reliable alternatives to $post AND get_queried_object(), that is quite evident from your comment. Your comment actually sparked something I was working on a while ago and completely forgot about, I think most of all, including me, are forgetting one very important global which is never modified (except by the filters and actions inside WP_Query itself), and that global is $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] holds the actual main query object. $GLOBALS['wp_query'] (AKA $wp_query) is only a copy of $GLOBALS['wp_the_query'].

added 3911 characters in body
Source Link
Pieter Goosen
  • 55.4k
  • 23
  • 115
  • 209

EDIT - Better alternative to get_queried_object()

From your comment to my answer

I understand $post can have been modified before I access it. But isn't that true also for $wp_query (modified through "custom" or "secondary" queries)? If so, shouldn't I test is_main_query() before relying on get_queried_object()? I'm assuming the main query is that based on the requested url, right? And if is_main_query() is false, what can I use then?

Very true, the main query object is stored in the $wp_query global variable. Using $wp_query as a local variable breaks the main query object and sets it to whatever you are using the global for. Also, query_posts sets the main query object to the current custom query, which also breaks it.

It is true that the queried object relies on the integrity of the main query object, which does make get_queried_object() vulnerable. In general, get_queried_object() is still much more reliable than $post because any custom query using the_post() or setup_postdata( $post ) sets the $post global to the current post in the current loop. Forgetting to reset a custom query with wp_reset_postdata() will leave you with the wrong post object inside $post.

As for get_queried_object(), if any one is still using query_posts, it is up to them if they want to suffer the consequences.

I like the idea that you would really want and are really looking at more reliable alternatives to $post AND get_queried_object(), that is quite evident from your comment. Your comment actually sparked something I was working on a while ago and completely forgot about, I think most of all, including me, are forgetting one very important global which is never modified (except by the filters and actions inside WP_Query itself*), and that global is $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] holds the actual main query object. $GLOBALS['wp_query'] (AKA $wp_query) is only a copy of $GLOBALS['wp_the_query'].

Lets quickly look at where this is set. In the current version (Wordpress 4.4.2), you will find the following code on lines 291 - 304 in `wp-settings.php

/**
 * WordPress Query object
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

I did not know WordPress way back when, but this was most probably done to accommodate query_posts, because if you look at wp_reset_query() which you should use after query_posts, it resets $wp_query back to $GLOBALS['wp_the_query'].

This all means that, even if we break the main query object ($wp_query), we still have a fully vaild copy left in $GLOBALS['wp_the_query'].

With all of this in mind, if you really need a 99.99% reliable way to get the current queried object, it would be $GLOBALS['wp_the_query']->get_queried_object(). That would be the ultimate reliable way without having to rerun the main query again by yourself.

Before I conclude, you also spoke about the is_main_query() check (which in essence checks if the current WP_Query instance is equal to $GLOBALS['wp_the_query']). In a case like this, it would not really work, as it simply return a boolean value.

CONCLUSION - wrapping up

To reliably get the current queried object on a single post page, or for that matter on any singular page and archive pages, use the queried object from the $GLOBALS['wp_the_query'] global

$GLOBALS['wp_the_query']->get_queried_object()

EDIT - Better alternative to get_queried_object()

From your comment to my answer

I understand $post can have been modified before I access it. But isn't that true also for $wp_query (modified through "custom" or "secondary" queries)? If so, shouldn't I test is_main_query() before relying on get_queried_object()? I'm assuming the main query is that based on the requested url, right? And if is_main_query() is false, what can I use then?

Very true, the main query object is stored in the $wp_query global variable. Using $wp_query as a local variable breaks the main query object and sets it to whatever you are using the global for. Also, query_posts sets the main query object to the current custom query, which also breaks it.

It is true that the queried object relies on the integrity of the main query object, which does make get_queried_object() vulnerable. In general, get_queried_object() is still much more reliable than $post because any custom query using the_post() or setup_postdata( $post ) sets the $post global to the current post in the current loop. Forgetting to reset a custom query with wp_reset_postdata() will leave you with the wrong post object inside $post.

As for get_queried_object(), if any one is still using query_posts, it is up to them if they want to suffer the consequences.

I like the idea that you would really want and are really looking at more reliable alternatives to $post AND get_queried_object(), that is quite evident from your comment. Your comment actually sparked something I was working on a while ago and completely forgot about, I think most of all, including me, are forgetting one very important global which is never modified (except by the filters and actions inside WP_Query itself*), and that global is $GLOBALS['wp_the_query']. $GLOBALS['wp_the_query'] holds the actual main query object. $GLOBALS['wp_query'] (AKA $wp_query) is only a copy of $GLOBALS['wp_the_query'].

Lets quickly look at where this is set. In the current version (Wordpress 4.4.2), you will find the following code on lines 291 - 304 in `wp-settings.php

/**
 * WordPress Query object
 * @global WP_Query $wp_the_query
 * @since 2.0.0
 */
$GLOBALS['wp_the_query'] = new WP_Query();
/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global WP_Query $wp_query
 * @since 1.5.0
 */
$GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

I did not know WordPress way back when, but this was most probably done to accommodate query_posts, because if you look at wp_reset_query() which you should use after query_posts, it resets $wp_query back to $GLOBALS['wp_the_query'].

This all means that, even if we break the main query object ($wp_query), we still have a fully vaild copy left in $GLOBALS['wp_the_query'].

With all of this in mind, if you really need a 99.99% reliable way to get the current queried object, it would be $GLOBALS['wp_the_query']->get_queried_object(). That would be the ultimate reliable way without having to rerun the main query again by yourself.

Before I conclude, you also spoke about the is_main_query() check (which in essence checks if the current WP_Query instance is equal to $GLOBALS['wp_the_query']). In a case like this, it would not really work, as it simply return a boolean value.

CONCLUSION - wrapping up

To reliably get the current queried object on a single post page, or for that matter on any singular page and archive pages, use the queried object from the $GLOBALS['wp_the_query'] global

$GLOBALS['wp_the_query']->get_queried_object()
Source Link
Pieter Goosen
  • 55.4k
  • 23
  • 115
  • 209
Loading