Words

Custom WordPress Post Queries & Meta Data Part 2

In part one we got to grips with WP_Query and and kept our custom queries pretty simple, but what if we want to display posts that meet one or two conditions set by custom fields in the admin area?

Querying By a Single Custom Meta Field

In part one we imagined a website with a custom post type for album reviews – now let’s imagine we only want to display reviews that have received a score of 5. I’ve included comments for each line to explain what’s happening:

1
2
3
4
5
6
7
8
9
$args = array( // Create our arguments array
‘post_type’ = ‘review’, // specify the type of post we want to query
‘meta_query’ = array( // Tells WordPress to query meta data using the arguments in this array
key= ‘score’, // Name of the meta field
‘value’ =5, // The value to be used in our query
‘compare’ ==, // How the post’s meta should compare to our value
‘type’ = ‘NUMERIC’ // The data type to expect
)
);

Querying by two Custom Meta Fields

In this example we want to return posts that have a score of 5 and are listed under the genre ‘rock.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$args = array(
‘post_type’ = ‘review’,
‘meta_query’ = array(
'relation' = 'AND', // Logical operator - we want both of the following to be true
array(
'key' = 'score',
'value' = '5',
'compare' = '=',
'type' = 'NUMERIC'
),
array( // Second array - holds the arguments we also want to use
'key' = 'genre',
'value' = 'rock',
'compare' = '='
)
)
);

I hope now you can see how extending the theory shown here you can create more advanced queries. While these posts focused largely on custom meta data, there are plenty of other options for querying posts, such as post meta information & taxonomies. For a full breakdown of what’s possible I’d recommend visiting the WordPress WP_Query Codex page.

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