Tag: WP_Query

Differences between using get_post() and WP_Query()

WordPress gives developers a number of ways to grab post content from the database. A lot has been written about the differences between using query_posts(), get_posts() and WP_Query, with WP_query being generally favored in most situations. But there is another method called get_post() which can fetch content for a single post, page or custom post object. If you want to output content from a single post object, you could technically use any 4 of these methods.

The question is, where does get_post() fit in with these other methods and what is the best way fetch the content of a single content object in the posts table?

The answer depends on your use case. Let’s say you want to show an excerpt of a specific post in your sidebar, what are the considerations? The get_post() function seems tailor made from grabbing a singular content object, which would make it a pretty obvious choice, but the other methods could also be used. When do you use what?

Ruling out get_posts() and query_posts()

If you’re just polling one object, be it a post, custom post, attachment or page and you know the post id, slug or post title of the object, we can easily rule out query_posts() as it is not a good fit. It wasn’t designed for this purpose and really is about showing multiple posts in a loop.

The difference between get_posts() and get_post() is larger than it seems. The main under-the-hood difference here is that get_posts actually uses WP_query and get_post() does not. So while we can use get_posts just fine for picking a single object, it’s not going to be as efficient as get_post() or as powerful as a custom WP_query. For that reason, let’s talk about the differences between those two.

WP_query vs get_post()

Let’s first look at a simple code example that will give you the same exact output using either method. Following along the lines of our use case example, we are grabbing a post with id 5 and displaying a title and an excerpt to that post.

<?php
// suppose we want to display an excerpt from a post with a post id of 5

// with WP_query

$args = array(
    'p' => 5
);
$custom_query = new WP_query( $args );

if( $custom_query->have_posts() ) {
   $custom_query->the_post();
   the_title();
   the_excerpt();
   wp_reset_postdata();
}
wp_reset_query();

// With get_post()

$get_content = get_post( 5 );
setup_postdata( $get_content );
the_title();
the_excerpt();
wp_reset_postdata();

One of the first things that you might notice is that the WP_Query example uses a loop and the get_post() example does not. The second thing you might notice is that get_post has a simpler way of specifying the post id. Let’s dig deeper into these two visually apparent differences.

On selecting the post object: get_post() vs WP_query

With WP_query you have to take into consideration what post type the object is that you are fetching. It is not enough to supply the ID or name of the post object. For example if it’s a post, you pass a parameter ‘p’ with the value of the post id, or ‘name’ with the name of the post. If it’s a page, you have to supply the parameter ‘pageid’ or ‘pagename’ respectively*. If it’s a custom post type, you have to pass along the post type of the object as a parameter, along with the parameters ‘p’ or ‘name’. With get_post() on the other hand, it’s suffices to supply the ID, name or slug of the post object: it doesn’t matter what post type the object is.

All in all, get_post is simpler that way. If you are coding functionality that lets a user supply any kind of post type, you have add some logic to build your query arguments correctly for WP_query.

Loop vs Non-Loop

With the WP_query example, we are using a loop, with get_post we are not. Why would it matter? Loops are a fundamental part of how typical WordPress themes render content, it’s handy to know a little more about their inner workings. Using a loop comes with some perks, such as the ability to use conditional tags that relate to the post being shown. Various functions provided by WordPress, the theme or a plugin might only work inside a loop and this is something to keep in mind.

If all you want to do is show some basic content from a post object, you might not need the loop and it will be simpler and more efficient to not use a loop.

Under the hood

There is a big difference in the way get_post() and WP_Query fetch content. When using WP_Query, we are running 4 queries to the database by default. One query fetches the data from the posts table, another fetches the custom fields from the meta table, a third query grabs author data from the user table and a fourth query gets data on comments relating to the post object from the comments table. While it is fairly efficient, you may not need all of the extra data and so those calls to the database might be a bit of an unnecessary waste.

With get_post() on the other hand, only one database query is made. You’ll note in the example above though that I’m using the setup_postdata() function (which enables the use of template tags such as the_title() ), which actually makes a database query of its own to grab info about the author. If you want to display author info, custom fields and/or comment data, you might favour WP_Query as it grabs this info for you in one swoop.

If you want to limit database queries to an absolute minimum and you’re only showing content contained in the posts table, there’s another way of writing the above get_post() implementation.

// accessing and rendering raw post data with get_post
$get_content = get_post( 5 );
echo apply_filters( 'the_title', $get_content->post_title ); 
if( $get_content->post_excerpt ) {
   echo apply_filters( 'the_excerpt', $get_content->post_excerpt );
} else {
   echo apply_filters( 'the_excerpt', $get_content->post_content );
}

This example should produce the same result as the previous examples, but it gives you a bit more control over what is going on.

Decision time

So when it comes to picking get_post() or WP_Query for displaying data from a specific post object, here’s a summary of considerations to keep in mind:

  • What data do you need to display? If you want to show comment counts, author data and custom fields, might as well use WP_Query. If you just need the data from the posts table, go with get_post(). You can save database queries with a get_post implementation.
  • Do you need a loop? If you need loop-specific functionality (conditional tags or certain plugin functionality that only works inside a loop), go with WP_Query. If you specifically want to avoid conditional tags working in relation to the post being grabbed, you should go with get_post().
  • UI consideration: Need to let users pick multiple kinds of post type in your user interface? It will be easier to code with get_post as passing parameters with WP_query is a bit more involved (you need to pass the post type as an argument). You’ll get slightly leaner, more elegant code with get_post().

Lastly – especially if you are going with WP_Query – and are concerned about performance you could consider a caching method to improve performance. This is pretty useful if, say, you want to show a certain post snippet in the sidebar on every page.

* With WP_Query you can also use the ‘p’ post id parameter to query a page providing you also set the ‘post_type’ parameter to page.