Should we trust the post globals?

@toscho left a comment to this answer which had me thinking again. How much trust should we have in the global scope, specially regarding the post globals like $post?

So what? The global variable can be overwritten from everyone before your check runs. That’s the point of global variables: global access.

$post for instance is surely one of the globals that is mostly modified either within the theme itself or by plugins. Yet it is also the global most commonly used in other applications within a given template, for instance, to setup related posts.

From answering (and commenting on) several posts with specific problems caused by the use of custom queries, it really stands out that most problems are caused due to custom queries not being reset (custom queries alter the globals set by the main query).

From this, it is apparent that $post is not reliable. Any poorly written piece of code that makes use of a custom query can alter the $post global, which in turn will break something (like related posts).

Only a handful of WordPress developers are actually knowledgeable enough in the inner workings of core and know what to avoid and what not. The greater population of users have no idea how the WordPress core operates.

They simply just download a theme and install plugins to do what is needed or even just copy code from a tutorial. Say they install a poorly written plugin which breaks their related posts on their single post, how will they know what caused that? Will they be able to sort that out themselves or will they be the hundredth person writing an email to the theme author about this problem, or posting a question on this site?

My question: How can you safeguard against such problems caused by other imported code when a global like $post is so unreliable? Should we be using a global like $post at all? What are the alternatives?

Just to share my mind here before I conclude: I have thought of (and seen in some themes and plugins, too) either using wp_reset_postdata() or wp_reset_query() before making use of $post, to make sure that the global is being reset to the main query’s $post. But why should I inflate my code in my theme because someone else did not properly code his plugin? And if someone did properly reset their custom query, this operation is run an unnecessary second time, which is not good.

The second method I thought of is making use of the $wp_query and then use its methods, something like $wp_query->post.

Any thoughts on this will be appreciated.

1

There is a sad truth: you can never ever be sure that some code will not break your code, and there is nothing you can do to prevent that. Especially in WordPress, where everything is global.

That said, yes, global $post is one of the most used global var, so using special care for it can be a good idea.

In my code I rarely directly access global $post.

When in singular contest, I use get_queried_object() and usually check if $post is a valid WP_Post instance:

$post = get_queried_object();

if ( ! $post instanceof \WP_Post ) {
   die( 'What the f**k?!' );
}

I do that check also in the rare cases I access $post directly.

Consider that get_queried_object() returns an unexpected value if some code uses query_posts, but hey, if someone uses code that relies on query_posts, they deserve it if their site breaks 🙂

Moreover, if I expect some conditions, I check for them, e.g. specific post types or a specific status.

If I need more checks and in more places, I create a function to perform them:

function get_global_post() {
    global $post;
    if ( 
        ! $post instanceof \WP_Post
        || ! $post->post_type === 'mycpt'
        || ! in_array( $post->post_status, array( 'publish', 'private' ), true ) 
    ) {
        return false;
    }
    return $post;
}

$mypost = get_global_post();

if ( ! $mypost ) {
      die( 'What the f**k?!' );
}

When inside a custom query, while looping, calling the_post() resets the post object, so it should be fine. Then it’s my responsibility to call wp_reset_postdata() after a custom query, and I do that, of course 🙂

Leave a Comment