BlueHelmet
BlueHelmet

Reputation: 541

Year and Month in Wordpress Archive List

I'd like to list all years from which there are public Wordpress posts, and in a sub-menu below, the months from those years. Example:

I have a working version of this inside a loop, but it requires me to manually add a new list every year. Is there any way to adjust it, so that it includes the new year automatically?

<h1>2016</h1>
<ul>
     <?php
$string = wp_get_archives('type=monthly&year=2016&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>
<h1>2015</h1>
 <?php
$string = wp_get_archives('type=monthly&year=2015&echo=0');
$pattern = ' ((19|20)\d{2}(</a>))';
echo preg_replace($pattern, '\\3', $string); '<li></li>';?>
</ul></a>

Upvotes: 5

Views: 14064

Answers (4)

Tahi Reu
Tahi Reu

Reputation: 590

I would do it this way.

It's a bit shorter and easier to understand, and it relies on WP core functions, which is usually the preferable way to handle the data in WP. Also, it doesn't need expensive regex functions.

1. Add "in_year" option to the wp_get_archives() function

<?php
    add_filter( 'getarchives_where', 'archives_in_specific_year', 10, 2 );
    function archives_in_specific_year( $sql_where, $parsed_args ) {
        if ( ! empty( $parsed_args['in_year'] ) ) {
            $year       = absint( $parsed_args['in_year'] );
            $sql_where .= " AND YEAR(post_date) = $year";
        }
        return $sql_where;
    }
?>

2. For each year, render that year and its months

<?php
    $args = [
        'type' => 'yearly',
        'echo' => false,
    ];

    $years       = wp_get_archives( $args );
    $years_array = explode( "\t", trim( wp_strip_all_tags( $years ) ) );

    foreach ( $years_array as $current_year ) {
        $current_year = intval( $current_year );

        $monthly_args = [
            'type'    => 'monthly',
            'format'  => 'custom',
            'echo'    => false,
            'before'  => '<span>',
            'after'   => '</span>',
            'in_year' => $current_year,
        ];

        $months = str_replace( ' ' . $current_year, '', wp_get_archives( $monthly_args ) );

        $yearly_args = [
            'type'    => 'yearly',
            'after'   => '<div>' . $months . '</div>',
            'in_year' => $current_year,
        ];

        wp_get_archives( $yearly_args );
    }
?>

Upvotes: 1

Purnendu Sarkar
Purnendu Sarkar

Reputation: 342

 <select name="archive-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;">
  <option value=""><?php echo esc_attr( __( 'Select Month' ) ); ?></option> 
  <?php wp_get_archives( array( 'type' => 'monthly', 'format' => 'option', 'show_post_count' => 1 ) ); ?>
</select>

Upvotes: 1

FATZOMBI
FATZOMBI

Reputation: 1

here's a simple mysql query, solved a similiar problem.

$query = 'SELECT DISTINCT MONTH(`post_date`) AS `month`, YEAR(`post_date`) AS `year` FROM `wp_posts` ORDER BY `post_date` ASC';
$results = $wpdb->get_results($query);

Upvotes: 0

BlueHelmet
BlueHelmet

Reputation: 541

Ok, found a very helpful post on stack exchange: here

Basically, add this to functions.php:

//List archives by year, then month
function wp_custom_archive($args = '') {
    global $wpdb, $wp_locale;

    $defaults = array(
        'limit' => '',
        'format' => 'html', 'before' => '',
        'after' => '', 'show_post_count' => false,
        'echo' => 1
    );

    $r = wp_parse_args( $args, $defaults );
    extract( $r, EXTR_SKIP );

    if ( '' != $limit ) {
        $limit = absint($limit);
        $limit = ' LIMIT '.$limit;
    }

    // over-ride general date format ? 0 = no: use the date format set in Options, 1 = yes: over-ride
    $archive_date_format_over_ride = 0;

    // options for daily archive (only if you over-ride the general date format)
    $archive_day_date_format = 'Y/m/d';

    // options for weekly archive (only if you over-ride the general date format)
    $archive_week_start_date_format = 'Y/m/d';
    $archive_week_end_date_format   = 'Y/m/d';

    if ( !$archive_date_format_over_ride ) {
        $archive_day_date_format = get_option('date_format');
        $archive_week_start_date_format = get_option('date_format');
        $archive_week_end_date_format = get_option('date_format');
    }

    //filters
    $where = apply_filters('customarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );
    $join = apply_filters('customarchives_join', "", $r);

    $output = '<ul>';

        $query = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC $limit";
        $key = md5($query);
        $cache = wp_cache_get( 'wp_custom_archive' , 'general');
        if ( !isset( $cache[ $key ] ) ) {
            $arcresults = $wpdb->get_results($query);
            $cache[ $key ] = $arcresults;
            wp_cache_set( 'wp_custom_archive', $cache, 'general' );
        } else {
            $arcresults = $cache[ $key ];
        }
        if ( $arcresults ) {
            $afterafter = $after;
            foreach ( (array) $arcresults as $arcresult ) {
                $url = get_month_link( $arcresult->year, $arcresult->month );
                $year_url = get_year_link($arcresult->year);
                /* translators: 1: month name, 2: 4-digit year */
                $text = sprintf(__('%s'), $wp_locale->get_month($arcresult->month));
                $year_text = sprintf('%d', $arcresult->year);
                if ( $show_post_count )
                    $after = '&nbsp;('.$arcresult->posts.')' . $afterafter;
                $year_output = get_archives_link($year_url, $year_text, $format, $before, $after);              
                $output .= ( $arcresult->year != $temp_year ) ? $year_output : '';
                $output .= get_archives_link($url, $text, $format, $before, $after);

                $temp_year = $arcresult->year;
            }
        }

    $output .= '</ul>';

    if ( $echo )
        echo $output;
    else
        return $output;
}

And then call this function on the page:

<?php wp_custom_archive(); ?>

It will return a list exactly as needed, by year then month, with links to each!

Upvotes: 5

Related Questions