1

In WordPress there are badly documented query parameters you can pass in a URL.

You can for example display posts in a specific category AND from a specific authour AND posted in a specific year:

/?category_name=CATNAME&author=AUTHOR&year=2015

What I'd love is to filter by a range. For example from the 1st of September 2015 to the 1st of September 2016, only using these URL parameters (not having to create a PHP custom page template).

I tried with ?year=<2015 but it doesn't work...

2 Answers 2

4

What you want isn't possible by ONLY using the query string parameters. However, you can create a function in your theme or a plugin that checks for the presence of a start_date and end_date parameter, for instance, and modify the query appropriately.

You'd want to add these functions as a filter to 'pre_get_posts', and check for the presence of the those two new parameters you'd create. Something like this, added to your theme's functions.php file should do it:

//Add in our new custom query vars first
function add_query_vars_filter( $vars ){
      $vars[] = "end_date";
      $vars[] = "start_date";
      return $vars;
    }
add_filter( 'query_vars', 'add_query_vars_filter' );

function parse_date_range_query_string( $query ){
  $start_date = get_query_var('start_date', 1900);
  $end_date = get_query_var('end_date', date("Y"));
  if (!is_admin()) { 
            $query->set('date_query', array(
                array(
                    'after' => array(
                            'year' => $start_date,
                            'month' => 1,
                            'day' => 1
                        ),
                    'before' => array(
                            'year'  => $end_date,
                            'month' => 12,
                            'day' => 31
                        ),
                    'inclusive' => true
                ),
            )
        );
    }
}

add_filter( 'pre_get_posts', 'parse_date_range_query_string' );

Now, a url like example.com/?start_date=2014&end_date=2016 should work

UPDATE: How would this work with a YYYY-MM-DD formatted string? Slight change, as the date_query before and after parameters can take a timestamp string instead of the year,month,day array I used above. You'd just change the function to something like the following:

function parse_date_range_query_string( $query ){
      $start_date = get_query_var('start_date', '1900-01-01');
      $end_date = get_query_var('end_date', date("Y-m-d"));
      if (!is_admin()) { 
                $query->set('date_query', array(
                    array(
                        'after' => $start_date,
                        'before' => $end_date,
                        'inclusive' => true
                    ),
                )
            );
        }
    }
Sign up to request clarification or add additional context in comments.

2 Comments

wow, thank you very much. Does this work with every PHP time format (if I change the date("Y") bit to reflect for example the YYYY-MM-DD format )?
My exact example wouldn't work for that, as you'd have to parse out the year, month, and day into separate variables. I'll update my answer to show how it might work with a YYYY-MM-DD formated date
2

Thanks for this solution... generally it works well.

For whatever reason, when selecting an "end" year that is less than the current year - ie... start_date=2014&end_date=2015, the page displays the correct posts, but hides the navigation menu.

If I change the end date to 2017, it shows the navigation menu.

EDIT: Found a solution to this; just in case this is happening for others. Adding in

if ( ! is_admin() && $query->is_main_query()){

just appends the new date range in the Main query, rather than every query (ie... the menu query).

Thus, the full code of the solution above will be:

//Add in our new custom query vars first
function add_query_vars_filter( $vars ){
      $vars[] = "end_date";
      $vars[] = "start_date";
      return $vars;
    }
add_filter( 'query_vars', 'add_query_vars_filter' );

function parse_date_range_query_string( $query ){
  $start_date = get_query_var('start_date', 1900);
  $end_date = get_query_var('end_date', date("Y"));
  if (!is_admin() && $query->is_main_query()) { 
            $query->set('date_query', array(
                array(
                    'after' => array(
                            'year' => $start_date,
                            'month' => 1,
                            'day' => 1
                        ),
                    'before' => array(
                            'year'  => $end_date,
                            'month' => 12,
                            'day' => 31
                        ),
                    'inclusive' => true
                ),
            )
        );
    }
}

add_filter( 'pre_get_posts', 'parse_date_range_query_string' );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.