Posted on: January 15, 2013

Custom WordPress Post Queries & Meta Data

Working on a project recently that required some advance querying of posts it became obvious that there was no clear instructions on querying WordPress posts by custom meta data – something anyone who’s customised  WordPress will no doubt have used.

It’s easy enough to get and display the meta data of a particular post but returning posts that match specified meta quires isn’t as well known, but once you get to grips with it you’ll see how the principals can be expanded to build complex WordPress based websites such as eCommerce stores or property websites that require advanced filtering.

Note: if you are comfortable with WP_Query and are looking for specific examples on querying custom meta data click here to visit part 2

Understanding WP_Query

A bare bones but recognisably standard WordPress loop may look like this:

1
2
3
4
5
6
7
8
<?php if(have_posts()) : while(have_posts()) : the_post(); ?>
<h1><?php the_title() ?></h1>
<div class=”post”><?php the_content() ?></div>
<?php endwhile; else : ?>
    Sorry, I couldn’t find any posts for you.
<?php
  endif;
?>

The above loop would be fine for a single.php or page.php template but it offers virtually no control over which posts are displayed. The solution then, is to use WP_Query which separates the query and the loop.

Using WP_Query

Let’s assume we have a custom post type called ‘review’ for album reviews on the website and we only wish to display these type of posts on a particular page.

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$args = array(‘post_type’ => ‘review’);
$reviews = new WP_Query($args);
if ($reviews->have_posts()) : while($reviews->have_posts()) : $reviews->the_post();
?>
    <h1><?php the_title() ?></h1>
    <div class=”post”><?php the_content() ?></div>
<?php endwhile; else : ?>
    Sorry, I couldn’t find any posts for you.
<?php
    endif;
?>

As you can see, much of the above is the same as the original loop – the difference comes at the start where we’re querying the database for certain posts.

Let’s look at it line by line:

$args = array(‘post_type’ => ‘review’);

Here we create a variable that holds an array of key – value pairs that WordPress will try to match when retrieving posts. WordPress allows for a range of arguments here but we’re starting simple – we want posts where the type is recorded as ‘review’.

$reviews = new WP_Query($args);

In this line we’re instantiating the WP_Query class and passing it the query we’ve built in the $args variable above. We place this instance of the class WP_Query in a variable so we have something to reference further down.

if ($reviews->have_posts()) : while($reviews->have_posts()) : $reviews->the_post();

The only difference between this line and the original loop is we’re referring to methods within the specific WP_Query class we want and to ignore any others. As WP_Query is held in the variable $reviews, we specify as much and tell PHP were to look. Essentially we’re saying:

Look inside $reviews and access its method ‘have_posts()’.

Next Steps

In our example we’re only using the title and content template tags but you’re free to access any of the usual tags such as author, published date, category etc.

Note that WP_Query works on non-custom meta data just as well. If you wanted to display posts in a particular category the following would be fine:

$args = array(‘cat’ =>1);

So far we’ve kept our queries pretty simple, only including one argument at a time, but what if we want to query posts by the values of custom fields?

Next: Querying Posts By Custom Meta Data