WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How do I limit the query by two custom meta fields, a start date and an end date? This is what my data looks like:

meta_key   | meta_value |
start_date | 20100131   | //Jan 15, 2010
end_date   | 20100206   | //Feb 6, 2010

$today = date(YYYYMMDD);

The post will show if start_date = $today and it will expires when end_date = $today.


Here is the structure on my single.php

First Query I use here your answer

query_posts( $query_string );
if (have_posts()) : while (have_posts()) : the_post();
    ?><a href="<?php the_permalink() ?>"><?php the_title() ?></a><br /><?php
endwhile; endif;

and Second Query with regular wordpress function but this second query doesnt work properly

if (have_posts()) : while (have_posts()) : the_post();
    ?><a href="<?php the_permalink() ?>"><?php the_title() ?></a><br /><?php
endwhile; endif;
share|improve this question
up vote 3 down vote accepted

Edited again to demonstrate adding and removing filters:

Include these general functions in your functions.php. These are the filters you will invoke for the loops where you want to limit your query by these two meta values:

function date_check_join( $join ) {
    global $wpdb;
    $join .= " JOIN ".$wpdb->postmeta." AS startdate ON 
        (".$wpdb->posts.".ID = startdate.post_id AND
        startdate.meta_key = 'start_date')
        JOIN ".$wpdb->postmeta." AS enddate ON 
        (".$wpdb->posts.".ID = enddate.post_id AND
        enddate.meta_key = 'end_date')";
    return $join;

function date_check_where( $where ) {
    $today = date('Ymd');
    $where .= " AND startdate.meta_value <= $today
    AND enddate.meta_value >= $today";
    return $where;

Now, on the page(s) where you want to include these filters, add them before the loops you want to filter and remove them afterward. For example:

add_filter( 'posts_join', 'date_check_join' );
add_filter( 'posts_where', 'date_check_where' );

query_posts( "yourqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop will only includes where today is between start_date and end_date
endwhile; endif;

query_posts( "anotherqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop also only includes where today is between start_date and end_date
endwhile; endif;

remove_filter( 'posts_join', 'date_check_join' );
remove_filter( 'posts_where', 'date_check_where' );

query_posts( "thirdqueryhere" );
if (have_posts()) : while (have_posts()) : the_post();
// This loop is not affected by the filters, so you can query for posts 
// where start_date is in the future, or end_date in the past, etc.
endwhile; endif;

You just need to add your conditions to the 'posts_join' and 'posts_where' filters before your search, and remove them afterwards (otherwise these conditions will be applied to everything on your site, including pages, menus, etc.)

If you can simplify this by only comparing against one field, then you can use the meta_compare attribute built into the WP_Query object. You could schedule your posts for the start_date (so they don't show ahead of schedule), and then compare the date against the end_date custom field when you query.

share|improve this answer
@Jan Fabry thanks for editing my post it was exactly what I want – Gerald Jan 17 '11 at 9:02
@goldenapples thanks for the answer. I tested the script above but it have an error here is at line 3 Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING – Gerald Jan 17 '11 at 9:03
@Gerald Oh. I left out a comma from the second line above. Try it now. I did test it out on my local server and I can confirm that it does work. – goldenapples Jan 17 '11 at 18:46
@goldenapples thank you! got it..but another issue it filter also the post in admin post listng.. .how what we can do so it will not affect the post list in admin side.. thanks – Gerald Jan 18 '11 at 8:07
@Gerald Ah... you're adding this code straight in your functions.php file. I was thinking that you would add these filters right before the loop you wanted to filter, then remove them afterward. If you want to filter all the loops on your site this way, then hook the filters onto something and test whether you're in the admin section or not before applying them. I'll edit my answer to give an example. – goldenapples Jan 18 '11 at 17:00

The answer to this question: How to Change Loop to Order Posts by Views (using wp-postviews plugin) shows you how to sort by a custom field.

Take a look at the Codex docs for query_posts(): http://codex.wordpress.org/Template_Tags/query_posts, and look a the custom field sections.

Then, all you need to do is include a test within the loop to skip if ($today < start_date or $today > end_date)

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.