WordPress: query posts with multiple custom fields

When you use custom fields to define multiple properties of posts and want to provide filtered views based on a combination of filters, you’ll first come to the function query_posts.

I assume here you know how to properly use query_posts e.g. you know you have to reset the query after using it (with wp_reset_query).

You can define what you want to retrieve in the arguments of the function e.g.:

query_posts( 'p=53' ); //will query the post with ID=53
query_posts( 'cat=6' ); //will query all posts in the category with ID=6

If you want to perform some more complex queries it is generally better to provide a query parameter array as argument than a query string:

$args=array('category_name' => 'my-category-slug', 
			'posts_per_page' => 10, 
			'orderby' => 'date', 
			'order' => 'ASC');

It makes it more readable and allows you to add a meta_query element to also filter according to a custom field:

$args=array('category_name' => 'my-category-slug', 
			'posts_per_page' => 10, 
			'orderby' => 'date', 
			'order' => 'ASC',
			'meta_query' => array(array('key' => 'my_custom_field_key',
										'value' => $my_custom_field_key))

Or even with multiple custom fields:

$args=array('category_name' => 'my-category-slug', 
			'posts_per_page' => 10, 
			'orderby' => 'date', 
			'order' => 'ASC',
			'meta_query' => array(array('key' => 'my_custom_field_key',
										'value' => $my_custom_field_key),
								  array('key' => 'my_custom_field_key2',
										'value' => $my_custom_field_key2))

While implementing the search form on kinderautositz-kaufen.de, I had to do something like this:

If the user chooses the value “value1″ in the filter, then display posts with the custom field set to “value1″ or “value1 or xxx” or “xxx or value1″.
If the user chooses the value “value2″ in the filter, then display posts with the custom field set to “value2″ or “value2 or xxx” or “xxx or value2″.

This makes it of course easier to directly work with SQL than to use arrays to define the criteria.

Here’s how I did it:

First you need to setup some filters to add the fields, joins and where clauses to the generate statement.

Add the following to your functions.php file (e.g. at the end of the file):

<?php function my_posts_fields ($fields) {
   global $my_global_fields;
   if ($my_global_fields) $fields .= $my_global_fields;
   return $fields;
function my_posts_join ($join) {
   global $my_global_join;
   if ($my_global_join) $join .= $my_global_join;
   return $join;
function my_posts_where ($where) {
   global $my_global_where;
   if ($my_global_where) $where .= $my_global_where;
   return $where;
function my_posts_orderby ($orderby) {
   global $my_global_orderby;
   if ($my_global_orderby) $orderby = $my_global_orderby;
   return $orderby;

You then need to update the global variables $my_global_fields, $my_global_join, $my_global_where and $my_global_orderby in your page template:

	if(!empty($_REQUEST['my_custom_field_key'])) {
		$mam_global_fields = $mam_global_fields . ', my_custom_field_key.meta_value my_custom_field_value';
		$mam_global_join = $mam_global_join . " JOIN $wpdb->postmeta my_custom_field_key
			ON ({$wpdb->posts}.ID = my_custom_field_key.post_id AND my_custom_field_key.meta_key = 'my_custom_field_key'
			AND (my_custom_field_key.meta_value = '{$_REQUEST['my_custom_field_key']}' OR my_custom_field_key.meta_value LIKE '%%{$_REQUEST['my_custom_field_key']} or %%' OR my_custom_field_key.meta_value LIKE '%% or {$_REQUEST['my_custom_field_key']}%%'))";
	if(!empty($_REQUEST['my_custom_field_key2'])) {
		$mam_global_fields = $mam_global_fields . ', my_custom_field_key2.meta_value my_custom_field_value2';
		$mam_global_join = $mam_global_join . " JOIN $wpdb->postmeta my_custom_field_key2
			ON ({$wpdb->posts}.ID = my_custom_field_key2.post_id AND my_custom_field_key2.meta_key = 'my_custom_field_key2'
			AND (my_custom_field_key2.meta_value = '{$_REQUEST['my_custom_field_key2']}' OR my_custom_field_key2.meta_value LIKE '%%{$_REQUEST['my_custom_field_key2']} or %%' OR my_custom_field_key2.meta_value LIKE '%% or {$_REQUEST['my_custom_field_key2']}%%'))";

You can then display the results like this:

<?php while ( have_posts() ) : the_post(); ?>
    <div class="entry">
        <header class="entry-header">
          <h2 class="entry-title"><?php the_title(); ?></h2>
		<div class="entry-content">
		</div> <!-- entry-content -->
	</div> <!-- entry -->
<?php endwhile; // end of the loop. ?>
Email this to someoneShare on FacebookShare on Google+Share on LinkedInDigg thisShare on RedditShare on StumbleUponTweet about this on TwitterBuffer this page

One thought on “WordPress: query posts with multiple custom fields

  1. Pingback: Scion Players | WordPress: query posts with multiple custom fields

Leave a Reply

Your email address will not be published. Required fields are marked *

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>

CommentLuv badge