Grow your CSS skills. Land your dream job.

Last updated on:

Custom Loop/Query Based on Custom Fields

This snippet enables you to make a custom loop that is purely based on custom-fields. Not dependent on any category or tag. This is not (yet) possible with query_posts() or WP_Query(), so we here utilize a direct $wbdb-call:

<?php

 $querydetails = "
   SELECT wposts.*
   FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
   WHERE wposts.ID = wpostmeta.post_id
   AND wpostmeta.meta_key = 'readmoretext'
   AND wpostmeta.meta_value = 'Go check this out'
   AND wposts.post_status = 'publish'
   AND wposts.post_type = 'post'
   ORDER BY wposts.post_date DESC
 ";

 $pageposts = $wpdb->get_results($querydetails, OBJECT)

 ?>

First we select any WordPress Posts that contain "meta data" (custom fields). We then add a few conditions. For example, the key should be "readmoretext", another condition is that the value of the custom field needs to be "Go check this out". Also, it needs to be published post, it needs to be an actual Post (not a Page), and in lastly in descending order.

You can remove, add or duplicate/change any of these AND conditions to get exactly the thing you need. (for example, all Posts that have a custom field called "mood", then get rid of the *. meta_value-line and then you'll get all the posts that have a "mood" set regardless of it's value.

After you've run the query, you can run a loop to output the results:

<?php if ($pageposts):
 foreach ($pageposts as $post):
       setup_postdata($post); ?>

               // Make your loop here. For example :
               <div <?php post_class(); ?>> id="post-<?php the_ID(); ?>">
               <h2><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>
               <?php the_content(); ?>
               </div>

 <?php endforeach;
endif; ?>

Comments

  1. Permalink to comment#

    This is great! What if you want to limit the loop to 5 posts/pages?

  2. Permalink to comment#

    Okay, that was easy. Just added LIMIT 4 to the query details…

  3. hmm..is it support wordpress 2.9???

  4. Permalink to comment#

    Great stuff, using it in several places in one of my wp templates.

    In addition to this, is there a way to query mulitiple custom fields and print the “merged” results?

  5. Isn’t this the same result you’d obtain using wp_query?

    Something like this:

    http://wordpress.pastebin.com/uJDdsiCw

    I used this reference:

    http://codex.wordpress.org/Template_Tags/query_posts#Custom_Field_Parameters

    but haven’t tried it yet.

    • It actually can. I just used it that way.
      I couldnt implement the code in the article whether for noobness or didnt understand where to put it.

      I got your code and integrated it with a simpler query;
      $loop = new WP_Query( $args );
      if($loop->have_posts()): while ( $loop->have_posts() ) : $loop->the_post();

    • Here’s an easier way to accomplish this task. http://pastie.org/2464333 It works like a charm every time!

    • sabbir
      Permalink to comment#

      The flexibility of using SQL query is more than custom post queries. For example if you want to search through a range or something like that.

  6. I’ve been trying to figure out, how to show posts from a specific category, if the page template being viewed has a custom field value with the same name.

    ie. a custom field value is present, and posts in a category with the same name as that custom field value are shown.

  7. carol
    Permalink to comment#

    I am trying to use this to output child pages of a certain parent page that have a particular custom field. Problem is it spits out more than one of the same child page depending on how many values have been declared for the custom field. That is if the child page has two different costume field VALUES for “soundfile” it will output that childpage twice. How can I limit that. Here is the link to the page I am working on:

    http://www.oliviablock.net/listen/

    Thanks in advance

  8. carol
    Permalink to comment#

    OK, by some freakin miricle I was able to figure out the solution to the above comment. Instead of OBJECT I used OBJECT_K which results output as an associative array of row objects, using first column’s values as keys so that duplicates where discarded.

    Thanks,
    carol

  9. Permalink to comment#

    Thanks for this Chris!!! You just saved my life with this one! :)

  10. Permalink to comment#

    Fantastic! This worked like a charm for me, thanks so much!

  11. Permalink to comment#

    Very nice Chris. This gives me the control I was looking for for out putting post content on my home page. Cheers mate.

  12. Fannar
    Permalink to comment#

    I wanted to thank you for this super useful post. It basically saved my life. I have spent so much time trying to do something similar with the wordpress built in queries and not been able to.

    Thank you !

  13. PG
    Permalink to comment#

    Really good post Chris, I almost thought it would solve a problem I’m having, which I’ve looked everywhere for info on but couldn’t find a solution. I’m hoping someone here will have some idea of how to do this or if it’s even possible.

    Below is part of the code from this post, my custom field is called ‘views’ and by using the wp-postviews plugin, that custom field is given the number of how many people have viewed that post. Is there any way to get the last line, instead of ordering the posts by date, to order them by the custom field view number values, in descending order? I’ve all but given up on trying, so if anyone knows I’d be very grateful!

    $querydetails = ”
    SELECT wposts.*
    FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
    WHERE wposts.ID = wpostmeta.post_id
    AND wpostmeta.meta_key = ‘views’
    AND wposts.post_status = ‘publish’
    AND wposts.post_type = ‘post’
    ORDER BY wposts.post_date DESC

  14. PG
    Permalink to comment#

    Just to update, someone else was kind enough to update the current code I had (not the one above) to order posts by view count. Just thought I’d share it below incase anybody is looking to do the same thing.

    $posts_per_page,
    ‘paged’ => $paged,
    ‘more’ => $more = 0,
    ‘meta_key’ => ‘views’,
    ‘orderby’ => ‘meta_value_num’,
    ‘order’ => ‘DESC’,
    ); ?>

    <div id=”post-”>

  15. This is a great post!
    With this script, based on custom fields, WordPress is more flexible.
    Thank you! You’ve saved my work. :)

  16. Permalink to comment#

    I know this is a year old post, but I have been searching for a solution to my problem and I have yet to find a solution.

    Code wise, I am using exactly what you have posted. However, the query only retrieves one result.

    Any ideas what might cause this?

    Thanks in advance!

  17. i am unable to change the loop query in the
    code

    how can i modify
    it by custom fields ..

    and query

    $paged = (get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1;
    $loop = new WP_Query();
    $loop->query( array( ‘post_type’ => ‘page’ , ‘meta_key’ => ‘portfolio_image’, ‘showposts’ => 5, ‘orderby’ => date, ‘order’ => ‘DESC’ ,’paged’=> $paged));

    please any one help me ….

  18. Actually i have ti implement the where and like conditions in the query.

    for the searching by a particular values

  19. 4nt0n
    Permalink to comment#

    Well indeed an old post but I would to implement the same query but with multiple conditions.somthing like this:

    $querystr = ”
    SELECT wposts.*
    FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta
    WHERE wposts.ID = wpostmeta.post_id
    AND wpostmeta.meta_key = ‘parent_cat’
    AND wpostmeta.meta_value = ‘methods’
    AND wpostmeta.meta_key = ‘main_item’
    AND wpostmeta.meta_value = ‘true’
    AND wposts.post_status = ‘publish’
    AND wposts.post_type = ‘post’
    ORDER BY wposts.post_date DESC
    “;

  20. Hi Chris

    I was just about to use this code when I spotted what I think to be a tiny error.

    On the line:

    <div <?php post_class(); ?>> id=”post-<?php the_ID(); ?>”>

    I think there is one too many ‘>’ after the first PHP segment. The div is being ended too soon.

  21. Abhijit Aitwade
    Permalink to comment#

    Great post! Solved custom fields sql problem.

    Thanks!

  22. Miles
    Permalink to comment#

    THANKS.. GREATT TUT REALLY HELPED.

  23. Permalink to comment#

    Works great, thanks so much! :-)

  24. Works great :) thanks for sharing it

  25. brilliant… (so is a lot of the design on this site, i might add!)
    one question… is there a “wildcard” option for wpostmeta.meta_value ?
    basically if there’s NO data in the meta_key i’ve selected, i want to hide the loop, but as long as there’s SOMETHING in it, i’d like it to appear…
    there are too many variables (and more added on occasion) to make it viable to have to hard code an array…

    i’ve tried $key and that works as long as there is a value, but when there is no value it actually displays the query output (with no data) twice…

  26. Swami.M

    I’m trying to use this to create a custom calendar, but because I’m very new at this, I am kinda lost. I know that I need to use the above code to pull out the meta data for the date. But the posting of the title and permalink within the specific date of the calendar is beyond me. I know that I can pull the title and permalink and display as above, but how can I get it to display in the correct date box for the calendar? Anyone got any ideas?

    PS: Like I said above, I’m very new at this, so I’m trying to figure things out as I go. Please excuse my ignorance.

  27. why not using this snippet? $the_query = new WP_Query(array( 'meta_key' => 'open', 'meta_value' => 'yes' ));

  28. Am going to have to use this for a really weird archive layout I’ve been asked to build; does anyone know how I’d go about using WordPress’ inbuilt pagination with these results? I know I can use OFFSET and LIMIT in the SQL nad do it manually, but I’d ideally like to hook into the default WordPress implementation if possible.

  29. Permalink to comment#

    Good stuff! Been using it for a bunch of queries! Thanks.

    • burki
      Permalink to comment#

      hi all.
      i need to check two meta keys and meta values. if any of the meta key and meta value is find then get the post and the related meta data.
      like
      where ( wpostmeta.meta_key = ‘any’
      AND wpostmeta.meta_value = ‘any’)
      Or

      ( wpostmeta.meta_key = ‘another’
      AND wpostmeta.meta_value = ‘another’),

      please help, and sorry for weak english.

  30. burki
    Permalink to comment#

    hi all.
    i need to check two meta keys and meta values. if any of the meta key and meta value is find then get the post and the related meta data.
    like
    where ( wpostmeta.meta_key = ‘any’
    AND wpostmeta.meta_value = ‘any’)
    Or

    ( wpostmeta.meta_key = ‘another’
    AND wpostmeta.meta_value = ‘another’),

    please help, and sorry for weak english.

  31. Sasha
    Permalink to comment#

    For those who don’t want to mess with the code, there is a very easy solution though the Advanced Post Types Order plugin more details at http://www.nsp-code.com/how-to-order-wordpress-posts-using-a-custom-field-value/<a/&gt;

  32. Jack
    Permalink to comment#

    Question about this. I understand that when using wp_query the metadata and other goodies are cached. Do you lose those speed benefits with this query?

  33. Permalink to comment#

    Now i am able to write custom queries to show post meta data which i wanted in my custom loop. You are Awesome :)

  34. Some good tips here but I am trying to get the custom field to be equal to the page title and that way I can have many pages using the same loop.

  35. Thank you for sharing of this snippet! You made my day!

  36. Julian
    Permalink to comment#

    Thanks , works perfect ! :)

  37. Amazingly, the MIN() & GROUP BY works and I was able to get the results I wanted via the “SQL” below, but am having some trouble.

    SELECT p.*, MIN(pm.meta_value) as date
    FROM $wpdb-&gt;posts p, $wpdb-&gt;postmeta pm
    WHERE p.ID = pm.post_id
    AND p.post_type = 'performances'
    AND p.post_status = 'publish'
    AND pm.meta_key in ('date_one','date_two','date_three','date_four')
    AND pm.meta_value &gt; NOW()
    GROUP BY p.ID
    

    Now I want to access that single MIN(pm.meta_value) as date per p.ID. That’s a vital piece of information and I don’t know how to get that returned in the resulting loop.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".