Query Post And Pages With Multiple Meta Values

— Custom fields give WordPress immense flexibility, by using them correctly you can create very complex applications with the same functionality you could only find in custom CMS. Now for us developers, one of the “problems” we might face using multiple custom fields is that there is no easy ( built in ) solution to query posts or pages based on these multiple values. If you want to do so you have to create a custom ( somewhat complex ) sql query which is clearly not an easy task for most people, and most important it ain’t a flexible solution you could just include from one project to another.

So in the look out for a nice and solid solution I came across this post by Jamie Oastler a fellow designer who was kind enough to publish this amazing function: get_post_meta_multiple.
I really encourage you to go ahead and read his post as he makes an excellent and clear explanation of how the function works and how to implement it in your project.

As good as it is, I found that I still needed a bit more flexibility to use it in my projects so I went ahead and made a few small improvements that others might find useful. These give you the option to make your query even more specific, you can:

  1. Select whether you want to retrieve only posts or pages.
  2. Pass a number ( or many numbers ) to select posts only from specific categories.
  3. Limit the number of posts you want to retrieve.


Get Post Meta Multiple Modified Function: ↓ Download

Usage Example

The usage of the function is really simple, as stated before Jamie made an excellent explanation on his blog, so no need to repeat all of that here again. The three new values I added can be assigned easily when calling the function as you can find in the example bellow:


<?php

/*
Function variables:

$aMetaDataList(array) example: array('meta_key' => 'meta_value','meta_key_2' => 'meta_value_2 )
$szType(string) = "post" or "page"
$szCategory(string) = example: '1' or '1,2,3'
$iLimit(integer)
*/

$aMetaDataList = array(
'custom_field_name_1' => 'Yes',
'custom_field_name_2' =>'No',
// etc…
);

$szCategory = '3'; // posts only from category 3
$iLimit = 6; // get only 6 posts

$my_posts = get_post_meta_multiple( $aMetaDataList, 'post', $szCategory, $iLimit );

// Once you have the posts just loop trough them as you would do usually

if ($my_posts):
foreach( $my_posts as $post ):

setup_postdata($post);

the_title();

endforeach;
endif;

?>

As you can see its very easy to use and it gives us developers huge flexibility to create amazing stuff. Props to Jamie for his great work. Hope you found this useful, if you have any suggestions please feel free to leave it on the comments, thank you!

The Function


<?php
function get_post_meta_multiple( $aMetaDataList = array(), $szType = 'post', $szCategory = NULL, $iLimit = NULL )
{
global $wpdb;

$szQuerystr = "SELECT p.* FROM $wpdb->posts AS p";

if ( $szCategory != NULL AND is_string($szCategory) )
{
$szQuerystr .= " LEFT JOIN $wpdb->term_relationships ON (p.ID = $wpdb->term_relationships.object_id) ";
$szQuerystr .= " LEFT JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id) ";
}

$szQuerystr .=  "WHERE p.ID IN ( ";

$szQuerystr .= "SELECT post_id FROM $wpdb->postmeta WHERE ";

$aInnerqry = array();

foreach($aMetaDataList as $szKey => $szValue)
{
$aInnerqry[] = $wpdb->prepare( "(meta_key = %s AND meta_value = %s)", $szKey, $szValue );
}

$szQuerystr .= implode(" OR ", $aInnerqry);

$szQuerystr .= " GROUP BY post_id ";
$szQuerystr .= "HAVING count(*) = " . count($aMetaDataList);

$szQuerystr .= ") AND p.post_status = 'publish' AND p.post_type = '".$szType."'";

if ( $szCategory != NULL AND is_string($szCategory) )
$szQuerystr .= " AND $wpdb->term_taxonomy.term_id IN(".$szCategory.")";

$szQuerystr .= " ORDER BY p.post_title ASC";

if ( $iLimit != NULL AND is_int($iLimit) )
$szQuerystr .= " LIMIT ".$iLimit;

$aMetaResults = $wpdb->get_results($szQuerystr, OBJECT);

return $aMetaResults;
}
?>

Tags: , ,

Friday, March 5th, 2010 WordPress

→ If you find this post useful please consider inviting me a cup of tea :) Thanks!

9 Responses to “Query Post And Pages With Multiple Meta Values”

  1. Thanks for the props Matt – and running with the concept. I should point out that while this does make it possible to query based on multiple custom fields (good) it does have an inherrent performance risk (bad) by virtue of the number of joins that the query to the database would be doing. For most sites / uses that won’t be too much of a red flag, but definitely something to be aware of.

    With 3.0 having custom post types and meta boxes, a lot of the areas where I would previously have used custom fields will be going towards that and Verve meta boxes plugin (wordpress.org/extend/plugins/verve-meta-boxes/) until that too finds its’ way into core.

  2. JamieO on March 5, 2010.
  3. Great post! thanks Jamie and Matt for sharing this, its just what i was looking for!! Maybe it would be a good idea to use it with WP Super Cache or any other similar plugin, just a thought tho. thanks again!

  4. Allan on March 6, 2010.
  5. @Jamie you are welcome, thanks for sharing the function and for the heads up, can’t wait to get my hands on 3.0 :)

    @Allan glad you found it useful, I agree about using a cache plugin and for more than this reason alone. tx for the comment!

  6. Matt on March 6, 2010.
  7. Hello,

    Thanks for solutions. I was looking for the same.
    But I want one more thing. I have a custom field ‘price’. I want to sort by price.

    That means.. meta_key is ‘price’ and meta_value = ‘$xxx’

    Is that possible ? How ?

  8. Jignesh on May 7, 2010.
  9. Can I have an ORDER BY meta key and meta value?

  10. Rubira on June 23, 2010.
  11. Hi there, nice query, but is missing a white space after that ‘p’ if you choose to ignore “category” or “limit” stuff..

  12. Homem Robô on July 8, 2010.
  13. Just wondering is this can handle comparisons or ranges, like if you have a key of price and you want to find all prices between 3 and 8.

    price >=3 and price <=8

    ?

  14. Ross on August 24, 2010.
  15. Thanks for codes Matt

    I just made some changes on codes.

    For who needs Order by, Order as, and Pagination please follow.

    http://netinial.com/blog/wordpress/wordpress-get_post_meta_multiple-pagination-and-ordering

  16. Deniz on August 28, 2010.

Leave a Reply

About Me

Matt Varone - Matias Varone - sksmatt
HI there,

I'm a freelance creative web developer, UI designer and hobbyist musician.

Twitter Status

Flickr Gallery

    Blue WallClutter drawerCS4 Replacement iconsCS4 Replacement icons