WordPress Wednesday: Query Posts by Custom Field Parameters

Geek Factor: 5

This WordPress Wednesday is part three of our epic series of Custom Field tricks, which has also included fawning over the excellent Custom Field Template plugin, and showing how we at Stem use Custom Fields in our internal and client projects.

In this post, we’re going to cover how to query posts by custom field parameters using the WP_Query class.

First, a quick review how to use WP_Query — for more information, check out this Greenhouse post from last year, or check out the invaluable WordPress Codex.

The WP_Query class allows you to create a brand-new query, rather than the default ones generated by WordPress on each post/page, and define the parameters however you see fit. This query is stored in a variable, and then can be used in the Loop by prefacing each step with the variable’s name.

In the example below, we stored the new query in a variable called $myCustomQuery. When we want to use that query in the Loop, we just need to include the $myCustomQuery-> variable (ie. $myCustomQuery->have_posts()).

Below we’re creating a new WP_Query and using it to query the five most recent posts in the ‘News’ category:

[php] '5', 'category_name'=>'news' )); // preface each step in the WordPress Loop // with the variable that holds the new WP_Query if ($myCustomQuery->have_posts()) : while ($myCustomQuery-> have_posts()) : $myCustomQuery->the_post(); ?>

[/php]

Using WP_Query and Custom Fields Values

Using custom field parameters in the WP_Query works much the same way.

To query posts that have specific custom field filled out, regardless of value, use the meta_key parameter — this would return all posts with a value (any value) for the custom field with the key ‘lunch’:

[php] $myQuery = new WP_Query('meta_key=lunch'); [/php]

You can also query by custom field values, regardless what field they’ve been added to — this returns any post with a custom field value of ‘sandwich’, regardless what field it appears in:

[php] $myQuery = new WP_Query('meta_value=sandwich'); [/php]

To query posts with a specific custom field and value, pair the meta_key parameter with the meta_value parameter — below will return all posts with the value ‘sandwich’ for the ‘lunch’ custom field:

[php] $myQuery = new WP_Query(array( 'meta_key' => 'lunch', 'meta_value' => 'sandwich' )); [/php]

It’s also possible to exclude certain custom fields or values from your queries, using the meta_compare parameter. As a default, the meta_compare operand is = (equal to) to compare the meta_value, but there’s also != (does not equal), > (greater than), >= (greater than or equal to), < (less than), and <= (less than or equal to).

For example, below we’re querying posts that do NOT have the value ‘sandwich’ in the ‘lunch’ field:

$myQuery = new WP_Query(array('meta_key' => 'lunch', 'meta_value' => 'sandwich', 'meta_compare' => '!='));

In WordPress 3.1 and higher, there is also the meta_query parameter, which allows for one or more arrays of custom field information to build queries from — using meta_query, the above query would look like this:

[php] $args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'lunch', 'value' => 'sandwich', 'compare' => 'NOT LIKE' ) ) ); $myQuery = new WP_Query($args); [/php]

Using meta_query works much the same as the separate meta_key, meta_value and meta_compare parameters, though it is formatted a bit differently. One thing to note is even when the meta_query value is technically a single item (the array that houses the associated key, value and compare), it’s still necessary to place it in an array as well.

The key and value parameters work the same as the meta_key and meta_value parameters in the earlier examples, although the value parameter allows strings as well as numeric arrays to display range for compariables. Compare is much like meta_compare, but also allows for the values BETWEEN and NOT BETWEEN, EXISTS and NOT EXISTS (in WordPress 3.5 and higher), LIKE and NOT LIKE, and IN and NOT IN.

Unlike using meta_value in your query, meta_query also allows you to combine multiple custom field queries. Below we’re querying for posts with the custom field ‘lunch’ and the value ‘sandwich’, and posts with the custom field ‘total’ with a value from 1 to 10:

[php] $args = array( 'post_type' => 'post', 'meta_query' => array( array( 'key' => 'lunch', 'value' => 'sandwich' ), array( 'key' => 'total', 'value' => array(1,10); 'compare' => 'BETWEEN' ) ) ); $myQuery = new WP_Query($args); [/php]

Now, Back to Those Lawyer Profiles and Practice Groups

Flip back to a couple of weeks ago, where we used the Custom Field Template to set up the practice areas to appear in the lawyer profiles as Custom Fields.

This enabled us to display the different practice group each lawyer belonged to on their profile pages, and have that Custom Field Template list automatically update when new practice areas pages were added to the site.

As was explained in that post, you can then display that list or practice areas on each lawyer profile by using the get_post_meta() function.

By querying pages using the custom field parameters, it’s also possible to pull this information in a ‘reverse’ fashion, and display the names of each lawyer that has a practice group checked on the practice page itself, even though that association has only been made in the lawyer profile custom fields.

Remember, the Custom Field Template that displayed the Practice Areas in our Lawyer Profiles had each practice area page’s ID as its value, rather than the title, making it possible to query the profiles with the current practice area’s page ID as a meta_value:

[php]

ID // each lawyer profile that has a 'Practice Area' value // matching that ID will be returned $practiceMembers = new WP_Query(array( 'post_type' => 'page', 'numberposts' => -1, 'meta_query' => array( array( 'key' => 'Practice Areas', 'value' => $post->ID )), 'orderby' => 'menu_order', 'order' => 'ASC' )); // if there are practice group members // display them with links in an unordered list if ($practiceMembers->have_posts()) : ?>

Practice Group Members

    have_posts()) : $practiceMembers->the_post(); ?>
[/php]

The output for this code would look a little like:

practice-group-members

Of couse, you could display any information that can be pulled from a standard WordPress post query. On our own projects, we’ve pulled basic job titles and contact information for Bernard & Partners, and added images for Waterstone Law.

I’d love to hear if anyone else has been using custom fields on their projects. Please share in the comments below!

  1. Aniket said:

    HI, i have been trying to add a filter on my search form using custom field. i am trying to build a ecommerce website where in i would like to have a price filter. My meta_key where price of each product is stored is mp_price_sort. I would like to sort my results based on price. Can you please help me out. I would like to have a dropdown orderby menu – which has couple of filters in it. so when anyone searches for a specific product or group of products, the user should be able to sort the products by price. Thank You.

    @ 12:13 am
  2. Hugo said:

    Hello Laurel,

    Looks great! Could you post the full code? I can’t seem to get it to work 🙁 I go missing when to loop gets to start…

    Thanks!
    Hugo

    @ 11:52 am

Leave a Comment

Note: Fields marked with a * are required; email addresses are not published.