Archive filtering posts by year and month

That’s trivial, we can exploit how WordPress URLs work and pass the query vars directly in the URL:

<form action="/" method="GET">
    <select name="year">
        <option value="2017>2017</option>
        ... etc ..
    </select>
    <select name="month">
        <option value="01>01</option>
        ... etc ..
    </select>

    <input type="submit" value="Filter"/>
</form>

WP will then see that it’s a date archive, it may even 301 redirect to the appropriate date archive ( my site redirected ?year=2019&m=01 to /2019/?m=01 ).

We can similarly make hyperlink versions with get_year_link and get_month_link.

The important part though, is that if you want a single list of years, and a single list of months, then you must restrict the months to a single year. The user will need to click on the year, and then on that years archive, click on the month.

First, display the years:

wp_get_archives( [
    'type'            => 'yearly',
    'format'          => 'html',
    'show_post_count' => 0,
] );

Then display individual months by specifying the year:

wp_get_archives( [
    'type'            => 'monthly',
    'year'            => is_year() ? get_query_var( 'year' ) : date('Y'),
    'format'          => 'html',
    'show_post_count' => 0,
] );

Finally we can filter the months to just that year with this:

    add_filter( 'getarchives_where', 'wp_get_archives_month_filter', 10, 2 );
    function wp_get_archives_month_filter($where, $args){
        if ( 'monthly' !== $args['type'] ) {
            return $where;
        }
        $year = $args['year'];
        $start = date( 'Y-m-d', strtotime( $year . '-01-01' ) );
        $end = date( 'Y-m-d', strtotime( $year . '-12-31' ) );
        $where.= ' AND `post_date` BETWEEN "' . $start . '" AND "'. $end . '"';
        return $where;
    }

Leave a Comment