How to Check if a WordPress Posts Exists by Its ID

I was recently having a conversation with a friend and fellow WordPress developer about the best ways to go about checking if a post exists given nothing but an ID.

For those who are experienced with the WordPress API, there are a number of ways to go about doing this. Functions and classes that exists for things like this are:

  • get_post
  • WP_Query
  • Running a direct query with $wpdb
  • …and so on

Each of these has its advantages and disadvantages, but of everything listed above, there are always two things I try to make sure that I do when working with simple functions (like checking on the existence of a post).

I try to make sure the function:

  1. Is as lightweight as possible
  2. Is as easy as possible to read within the context of the existing code

After all, months from now, you never know if you’ll recall why you wrote code a certain way nor will your team or your peers necessarily know why the code you selected is set in a certain way.

Check if a Post Exists by ID

First, assume that the only information that you have about a post is its ID. We’re not going to be worrying about functions that are useful within The Loop, nor are we going to be worried about functions that accept things such as the title, the content, the slug, or anything like that.

When trying to keep functions as lightweight as possible, it’s best to try to aim for something that returns as little information as possible but still gets you exactly what you need.

For example, one of the problems of using WP_Query (as much as I’m a fan of that particular class) is that it will return the entire post object. That’s a bit much for simply having to determine if a post exists.

Similar arguments can be made for get_posts and the idea of using $wpdb circumvents any of the provided APIs, is right up against the core database, and makes code even more difficult to read because you’re nesting one language – that is, SQL – in another language – that is, PHP – and then you’re assuming that the database schema will never change and that a fellow programmer will be able to understand your query.

For this reason alone, sticking with the API is almost a better solution.

So What Function Works?

Though I assume there are a number of functions that have come to mind (not to mention post_exists which I’ll address in a moment), one of the easiest ways that I’ve found is to use get_post_status.

First, the description of the function seems to describe exactly what’s needed:

Retrieve the post status based on the Post ID.

Then, the return value could be simpler: It’s a string of the status (if the post exists), or its false if the post doesn’t exist.

So this means we could write something like this in order to check if a post exists:

The thing about this code is that although it works and although it makes sense to those who are familiar with the WordPress API, it still reads a bit more cryptic than necessary especially given the fact that we’re simply trying to check if a post exists.

When it comes to situations like this, I find it useful to write a simpler helper function that essentially wraps the functionality in another function that makes the code easier to read within the context of a conditional.

For example, something like this:

Then, you can easily write if ( acme_post_exists( $id ) ) { } and so on.

For some, I understand why this may be overkill and I understand that it might feel weird to wrap a function that’s especially already telling us what we need to know, but when it comes to working with a codebase in the future, having reusable code, or having to maintain an existing function, then doing this makes the code as clear as possible.

Personally, I don’t find this contrived and its something that I would do – and have done – in my own work (granted, I may prefix the function to match the name of the theme as seen in the gist above if I were doing this outside of the class, but that’s not the point of this post) and small things like this can go a long way in making your code more of a pleasure with which to work.

What About post_exists?

A function called post_exists is actually available within the API and you can read more about it here. The problem with this particular post is that it requires:

  • The post title
  • Optionally, the post content
  • And optionally, the post date

Given the fact that from the outset of this post, I said that I was looking to find a post by its ID, this automatically becomes incompatible. Secondly, if I had more than the title, it would stand to reason that I likely – admittedly, not always – already have more information about the post such that I know it exists.

In short, I think this function is kind of weird.

However, I also recognize that functions don’t often make it into an application, let alone core, without them under going some type of use case and triage so I’m sure that the reason the function exists has more to do with something outside the case of this post.

At any rate, there it is: A light-weight, easy to use way to check if a WordPress post exists by its ID.

6 Comments

Thanks for a great post! Always appreciate these little nuggets of coding goodness.

FYI, it seems that post_exists is intended for use during importing: https://core.trac.wordpress.org/changeset/10722

For such a purpose, and with the way current importing works, I can understand a check on title/content/date. The import features of WordPress could definitely use some attention moving forward.

    For such a purpose, and with the way current importing works, I can understand a check on title/content/date. The import features of WordPress could definitely use some attention moving forward.

    Ah, good point.

Tom, because of PHP if logic, can’t you just use the existing function without the custom function?

if ( get_post_status( $id ) ) { //do something }

Strings are considered “true” and false is considered “false”?

    In short, yes you’re right but it comes at the expense of assuming several things:

    • The person maintaining the code understands what the function returns (which can be a string or a boolean)
    • get_post_status is not as clear as post_exists – it looks like we’re trying to do something different than we are
    • We’re trying on the dynamic typing of PHP which I’m not really against, but if we can reduce a function to returning a single type (such as a boolean), I’m usually a fan of that.

    So you’re definitely right, but from a readability and maintenance standpoint, I’m not as much as a fan of that approach.

It would be interesting to know how much more memory is used to process a script with your wrapper as opposed to running it without. I totally agree with your comment about making the intent of the function more explicit and have in the past written about coding for both primary and secondary audiences at http://foxdellfolio.com/primary-and-secondary-audiences/. But even though a few bytes may not matter, I think it does help to understand what is happening at the lowest level, for example Pippin Williamson wrote about the dangers of gettext filter https://pippinsplugins.com/dangers-gettext-filter/. So what seems like a small thing can have big consequences.

This is the only argument that I can see about the approach you have taken. In general I take a similar approach because I hope to makes the code cleaner and clearer.

    It would be interesting to know how much more memory is used to process a script with your wrapper as opposed to running it without.

    In more complex cases, I agree, but when it comes to writing a simple wrapper function that’s communicating with a function that returns either a string or a boolean, it’s not going to be much.

    Off the top of my head, I don’t know how many bytes these take up in memory as far as PHP is concerned, but I think this would be a much different story if we were working with a complex object with references all over the place, or something like that.

    So what seems like a small thing can have big consequences.

    Absolutely! And my previous comment isn’t meant to undermine this; however, a lot of it also has to do with understanding the callstack and how much demand is placed on the platform to execute a single function.

    Opening up a debugger or even just tracing the code in core should be easy enough for something like this. Though, again, I don’t want to downplay your strategy here in the context of a larger, more widely scoped situation.

    In general I take a similar approach because I hope to makes the code cleaner and clearer.

    Exactly :).

Leave a Reply

Name and email address are required. Your email address will not be published.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>