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;
}