4/13/2008 ↓

How to Only Retrieve Posts With Custom Fields

Author: Ronald Huereca Category: HOW-TO, WordPress, WordPress Hack

Thanks for visiting! If you're new here, you may want to subscribe to our RSS feed. This blog posts regular Wordpress news, updates of themes, plugins, ideas, hacks, quick fixes and everything about blogging, especially about Wordpress. Go ahead, subscribe to our feed! You can also receive updates from this blog via email.

One question I come across a lot regarding custom fields is how to only retrieve posts based on a custom field.

For example, if a post has a custom field of “MyData”, someone might want to only retrieve that particular post.

The WordPress Codex has a technique for retrieving posts based on custom fields, which consists of writing your own query and going through the results.

The technique in the Codex is good, but I’ve found a re-usable way one can retrieve only posts with certain custom fields.

The technique I use makes use of two custom functions placed in a theme’s “functions.php” and a custom WordPress Loop.

Let’s get started — The “functions.php” file

First, let’s place the two custom functions in the “functions.php” file. This file should be in your theme directory, but if it isn’t there, you can create one using any text editor.

Here are the two functions below:

function get_custom_field_posts_join($join) {
	global $wpdb, $customFields;
	return $join . "  JOIN $wpdb->postmeta postmeta ON (postmeta.post_id = $wpdb->posts.ID and postmeta.meta_key in ($customFields)) ";
}
function get_custom_field_posts_group($group) {
	global $wpdb;
	$group .= " $wpdb->posts.ID ";
	return $group;
}

The function “get_custom_field_posts_join” makes use of an advanced WordPress filter called “posts_join“. Each time posts are called, you can add on extra MySQL parameters using filters. In this case, I add on an option to find certain postmeta. Please note the use of a global variable called “customFields“, which I’ll explain a bit later.

The function “get_custom_field_posts_group” makes use of another advanced WordPress filter called “posts_group“. This is used to avoid duplicate entries in our return query.

Now Let’s Work on Our Loop

After the two functions are placed in the “functions.php” file, it’s time to work on placing the appropriate code into one of our template files.

For this example, I’ll be modifying the “sidebar.php” file in the WordPress default theme. You could place the below code in any of your theme files, however.

<?php /* Begin Custom Field Posts */ ?>
<h2>Custom Posts</h2>
<ul>
<?php
global $customFields;
$customFields = "'Links', 'MyData'"; //Comma seperated 's1', 's2', 's3'

The first part of the code deals with establishing the structure of the output. You really could do anything you want here.

Please note the use of the global variable “customFields“. What we’re doing here is setting up a comma-separated variable that will be used to search for our custom fields. The “customFields” variable is used in the “get_custom_field_posts_join” function.

In this example, it is assumed we want to find posts with custom fields of “Links” and “MyData“.

Custom Fields - Links and MyData
Custom Fields - Links and MyData

The next bit of code instantiates a new instance of WP_Query and runs a query to return some posts.

$customPosts = new WP_Query();
add_filter('posts_join', 'get_custom_field_posts_join');
add_filter('posts_groupby', 'get_custom_field_posts_group');
$customPosts->query('showposts=5' );//Uses same parameters as query_posts
remove_filter('posts_join', 'get_custom_field_posts_join');
remove_filter('posts_groupby', 'get_custom_field_posts_group');

Note the use of the “add_filter” and “remove_filter” functions. Since we are doing a post query, we can tap into the query and add our own parameters. So before the query is initiated, two query-type filters are added, and after the query is initiated, the two filters are deactivated since we only want them run once.

This last bit of code initiates our custom loop, gets the custom values, spits them out, and ends the loop.

while ($customPosts->have_posts()) : $customPosts->the_post();
$links = get_post_custom_values("Links");
$data =  get_post_custom_values("MyData");
?>
<li><a href='<?php echo $links[0]; ?>'><?php echo $data[0]; ?></a></li>
<?php endwhile; ?>
</ul>
<?php /* End Custom Field Posts */ ?>

The “get_post_custom_values” WordPress function returns an array of matching keys. It’s assumed there is only one key per post, which is why we echo out the first value (Ex: echo $links[0]).

The Full Post Code

Here is the full post code. The only thing you need to change for your own use is the custom fields needed (change the customFields text) and what type of output is desired within our custom loop.

<?php /* Begin Custom Field Posts */ ?>
<h2>Custom Posts</h2>
<ul>
<?php
global $customFields;
$customFields = "'Links', 'MyData'"; //Comma seperated 's1', 's2', 's3'
$customPosts = new WP_Query();
add_filter('posts_join', 'get_custom_field_posts_join');
add_filter('posts_groupby', 'get_custom_field_posts_group');
$customPosts->query('showposts=5' );//Uses same parameters as query_posts
remove_filter('posts_join', 'get_custom_field_posts_join');
remove_filter('posts_groupby', 'get_custom_field_posts_group');
while ($customPosts->have_posts()) : $customPosts->the_post();
$links = get_post_custom_values("Links");
$data =  get_post_custom_values("MyData");
?>
<li><a href='<?php echo $links[0]; ?>'><?php echo $data[0]; ?></a></li>
<?php endwhile; ?>
</ul>
<?php /* End Custom Field Posts */ ?>

Custom Field Output
Custom Field Output

Downloadable Code

The full code mentioned in this post is available for download. Within the “zip” file are a sample “functions.php” and “sidebar.php“.

Conclusion

With the above technique, you can do some pretty fancy stuff. For example, you can only retrieve posts with custom images for a nice magazine effect.

If you have any questions regarding the code, I’ll do my best to answer them in the comments.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.5 out of 5)
Loading ... Loading ...
Sphere: Related Content | stumbleit |
Translate to German Translate to Spanish Translate to French Translate to Italian Translate to Portuguese Translate to Japanese Translate to Korean Translate to Russian Translate to Chinese

Latest Videos

22 Comments | Leave a comment | Comments RSS

  1. Ronald, excellent post! I haven’t had a chance to test it yet, but I look forword to giving it a try.

    John Kolbert (14 comments.) — 04/13/2008 @ 7:42 pm
  2. @John,
    Good luck with it. Hopefully it works out for you.
    Ronald Huereca (48 comments.) — 04/13/2008 @ 8:18 pm
  3. I bow to you and your l33t mastery of WordPress Loop. I would totally do a highlander reference, but I’ll have to make sure that everyone gets it. So I’m not, but yeah “There can only be one!”

    I do like the current set of articles, but think that they should also be in the Codex.

    Jacob Santos — 04/13/2008 @ 9:23 pm
  4. @Jacob,
    By all means, go for it :) - the Codex that is, not the highlander reference.
    Ronald Huereca (48 comments.) — 04/13/2008 @ 9:30 pm
  5. Thanks for writing this article, it seems very close to something I would like to be able to do, except with pages. Do you know of a relatively easy way to get this to work with pages instead of posts?

    Matt Goff (1 comments.) — 04/13/2008 @ 10:34 pm
  6. @Matt,

    No, I haven’t played around with pages a whole lot. Perhaps you can try tapping into the ‘posts_where’ filter if you want to limit the results further.

    Can anyone else help Matt with this?

    Ronald Huereca (48 comments.) — 04/13/2008 @ 10:48 pm
  7. [...] How to Only Retrieve Posts With Custom Fields (tags: wordpress) [...]

  8. very nice! it would also be handy to have something like this that matched key/value pairs (where x=y in custom fields).

    DFOE — 04/15/2008 @ 4:19 am
  9. Pages are just posts with a different post_type.

    I haven’t tried it, but this _may_ work (I’ve only glanced at query.php):

    $customPosts->query('showposts=5&post_type=page');

    Viper007Bond (19 comments.) — 04/15/2008 @ 5:33 am
  10. This only lists posts with defined custom fields. Is there any way to still append posts without custom fields? And does paging work with this solution? Thanks!

    Ekro — 04/15/2008 @ 8:42 am
  11. Thanks for the tip! Very helpful. I was only aware of the_meta() template tag which isn’t nearly as flexible as get_post_custom_values().

    Gordon Brander (2 comments.) — 04/15/2008 @ 11:52 am
  12. @Viper,
    Thanks for weighing in.

    @Ekro,
    This technique only returns posts just with custom fields. Paging doesn’t currently work. I’ll probably write a separate post on that.

    Ronald Huereca (48 comments.) — 04/15/2008 @ 12:42 pm
  13. Great post! Thanks! I’d done something similar but basically used a query object and pulled everything out that way. Is this way more efficient? On my personal site I’ve implemented something using your mechanism, but I’m wondering if it’s worth updating my other project…this way is slightly cleaner I think. Very interested to know if it’s more efficient. Thanks!

    Dan (4 comments.) — 04/15/2008 @ 5:28 pm
  14. Hi…
    You have many excellent articles, tutorials and posts about Wordpress. Can I translate them to my native language (Bahasa Indonesia) and place them on my blog leaving the original link to you???

    Thank you very much…

    Kang Oedin (1 comments.) — 04/16/2008 @ 9:04 pm
  15. @Kang,
    Please get in contact with Mark via the WLTC contact form. He’ll be able to answer your question.
    Ronald Huereca (48 comments.) — 04/16/2008 @ 10:57 pm
  16. @Dan,
    This way is perhaps more reusable. More efficient? Not likely. If anything, I’d say your technique and this one are about the same. Both make use of one query. The only difference is, I modify the query for posts using built-in WordPress filters. You probably call a query directly.
    Ronald Huereca (48 comments.) — 04/16/2008 @ 10:59 pm
  17. [...] Menampilkan Posting Berdasarkan Custom Field Tertentu Posted by Kang Oedin April 17, 2008 Translated from How to Only Retrieve Posts With Custom Fields [...]

  18. [...] ici, on vous propose de créer une boucle Wordpress entièrement grâce aux Query Posts et de récupérer des articles via les champs personnalisés de Wordpress, les fameux “Custom [...]

  19. Thank you so much for this post! I was trying to figure it out myself, but that didn’t work.
    @Viper: that works!

    Maria — 04/20/2008 @ 11:22 am
  20. Thanks a lot, I was just trying to look for something like that.
    The only question - I’m really far from being an expert in coding - how can you then order the fields according to a custom field ?

    Marie-Aude (1 comments.) — 04/21/2008 @ 6:01 am
  21. Great how-to !

    vnvsven (2 comments.) — 04/23/2008 @ 6:32 am
  22. Is it possible to use this code also for pages with custom fields?

    vnvsven (2 comments.) — 04/23/2008 @ 10:54 am

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(required)

(required, will not be published)


S2