wp_get_archives()WP 1.2.0

Display archive links based on type and format.

1 time — 0.004392 sec (very slow) | 50000 times — 111.96 sec (extremely slow) | PHP 7.0.5, WP 4.4.2

Return

null|String. Void if 'echo' argument is true, archive links if 'echo' is false.

Usage

wp_get_archives( $args );
$args(string|array)

Default archive links arguments. Optional.

Default: ''

  • type(string)
    Type of archive to retrieve. Accepts 'daily', 'weekly', 'monthly', 'yearly', 'postbypost', or 'alpha'. Both 'postbypost' and 'alpha' display the same archive link list as well as post titles instead of displaying dates. The difference between the two is that 'alpha' will order by post title and 'postbypost' will order by post date.
    Default: 'monthly'

  • limit(string|int)
    Number of links to limit the query to.
    Default: empty (no limit)

  • format(string)
    Format each link should take using the $before and $after args. Accepts 'link' (<link> tag), 'option' (<option> tag), 'html' (<li> tag), or a custom format, which generates a link anchor with $before preceding and $after succeeding.
    Default: 'html'

  • before(string)
    Markup to prepend to the beginning of each link.
    Default: ''

  • after(string)
    Markup to append to the end of each link.
    Default: ''

  • show_post_count(true|false)
    Whether to display the post count alongside the link.
    Default: false

  • echo(true|false|int)
    Whether to echo or return the links list.
    Default: 1|true to echo

  • order(string)
    Whether to use ascending or descending order. Accepts 'ASC', or 'DESC'.
    Default: 'DESC'

  • post_type(string)
    Post type.
    Default: 'post'

  • year(string)
    Year.
    Default: current year

  • monthnum(string)
    Month number.
    Default: current month number

  • day(string)
    Day.
    Default: current day

  • w(string)
    Week.
    Default: current week

Examples

0

#1 Display an archive of posts grouped by month.

Only the last 12 months will be shown:

<?php wp_get_archives('type=monthly&limit=12'); ?>
0

#2 Display an archive of posts grouped by day

Only the last 14 days will be shown, with count total for each day in parentheses, e.g. “November 2, 2015 (3)”.

<?php wp_get_archives( [ 'type'=>'daily', 'limit'=>14, 'show_post_count' => 'true' ] ); ?>
0

#3 Display a list of the last 20 posts and sort it by title:

<?php wp_get_archives( 'type=postbypost&limit=20&format=custom' ); ?>
0

#4 Display the drop-down list of the archive by month in the HTML tag <select>

The number of posts for each month will be displayed next to it:

<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( 'type=monthly&format=option&show_post_count=1' ); ?>
</select>
0

#5 Display a list of all posts in alphabetical order.

Might come in handy for a site map:

<?php wp_get_archives( 'type=alpha' ); ?>
0

#6 Add rel=nofollow to links from the list

If you want to add rel="nofollow" to all links from the list, you can use this function call:

$archives = wp_get_archives( [
	'echo'   => 0,
	'type'   => 'postbypost',
	'limit'  => 3,
	'format' => 'html',
] );

echo str_replace( '<a', '<a rel="nofollow"', $archives );
0

#7 Filter a specific category/term

To filter a specific category/term, we have a specific case to add filters. It works in case we wish to change archive link based on get_query_var( 'news_category' ).

For example, on same template we have:

– News Category #1 has dropdown of 2019, 2018, 2017.
– News Category #2 has dropdown of 2017.

If the user access /news/news-category-2/2019, it will return no posts. We should disable an archive link 2018, 2019 if a current category is News Category.

The below code work with Taxonomy “news_category” and custom post type “news”. To work with default post, you should change back to Taxonomy “category” and default post “post”.

In templates/custom-archive-template.php

add_filter( 'getarchives_where', 'custom_archive_by_category_where' );
add_filter( 'getarchives_join', 'custom_archive_by_category_join' );

$args = array();

wp_get_archives( [
	'type'            => 'yearly',
	'format'          => 'option',
	'post_type'       => 'news',
] );

remove_filter( 'getarchives_where', 'custom_archive_by_category_where' );
remove_filter( 'getarchives_join', 'custom_archive_by_category_join' );

In functions.php:

function custom_archive_by_category_join( $x ) {
	global $wpdb;

	return $x . " 
		INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) 
		INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
}

function custom_archive_by_category_where($x) {
	global $wpdb;

	$current_term_slug = get_query_var( 'news_category' );

	if (!empty($current_term_slug)) {

		$current_term = get_term_by('slug', $current_term_slug, 'news_category');

		if (is_wp_error($current_term) ) {
			return $x;
		}

		$current_term_id = $current_term->term_id;

		return $x . " 
			AND $wpdb->term_taxonomy.taxonomy = 'news_category' 
			AND $wpdb->term_taxonomy.term_id IN ($current_term_id)";

	}

	return $x;
}

Read more about https://developer.wordpress.org/reference/hooks/getarchives_where/ and https://developer.wordpress.org/reference/hooks/getarchives_join/

0

#8 Get array with name and value keys

To return an array of years with name and value only like:

array(
   array(
	  'name' => 'January 2020',
	  'value' => 'http://demo.com/2020/01/'
   ),
   array(
	  'name' => 'February 2020',
	  'value' => 'http://demo.com/2020/02/'
   )
)

We must capture using echo=false&format=custom:

function theme_name_get_year_archive_array() {
	$years = [];

	$years_args = [
		'type'      => 'monthly',
		'format'    => 'custom',
		'before'    => '',
		'after'     => '|',
		'echo'      => false,
		'post_type' => 'news',
		'order'     => 'ASC',
	];

	// Get Years
	$years_content = wp_get_archives( $years_args );
	if( ! empty( $years_content ) ){
		$years_arr = explode( '|', $years_content );
		$years_arr = array_filter( $years_arr, function( $item ) {
			return trim( $item ) !== '';
		} ); // Remove empty whitespace item from array

		foreach( $years_arr as $year_item ){
			$year_row = trim( $year_item );
			preg_match( '/href=["\']?([^"\'>]+)["\']>(.+)<\/a>/', $year_row, $year_vars );

			if( ! empty( $year_vars ) ){
				$years[] = [
					'name'  => $year_vars[2], // Ex: January 2020
					'value' => $year_vars[1] // Ex: http://demo.com/2020/01/
				];
			}
		}
	}

	return $years;
}
0

#9 Display the titles of the last 20 posts

Uses custom as the value for the format argument and specifies before and after values (so, in this example, prints the titles within span tags and separated by commas):

<?php
wp_get_archives( [
	'type'   => 'postbypost',
	'limit'  => 20,
	'format' => 'custom',
	'before' => '<span class="my-post-title">',
	'after'  => '</span>, ',
] ); 
?>
0

#10 Custom wrappers on each link

An example using custom wrappers on each link item in the archive.

Helpful if you are doing special styling that require a more complicated structure.

<?php
$args = array(
	'type'            => 'monthly',
	'limit'           => '',
	'format'          => 'custom',
	'before'          => '<div class="sub-item">',
	'after'           => '</div>',
	'show_post_count' => false,
	'echo'            => 1,
	'order'           => 'DESC'
);

wp_get_archives( $args );
?>

Notes

  • See: get_archives_link()
  • Global. wpdb. $wpdb WordPress database abstraction object.
  • Global. WP_Locale. $wp_locale WordPress date and time locale object.

Changelog

Since 1.2.0 Introduced.
Since 4.4.0 The $post_type argument was added.
Since 5.2.0 The $year, $monthnum, $day, and $w arguments were added.

Code of wp_get_archives() WP 5.9.3

function wp_get_archives( $args = '' ) {
	global $wpdb, $wp_locale;

	$defaults = array(
		'type'            => 'monthly',
		'limit'           => '',
		'format'          => 'html',
		'before'          => '',
		'after'           => '',
		'show_post_count' => false,
		'echo'            => 1,
		'order'           => 'DESC',
		'post_type'       => 'post',
		'year'            => get_query_var( 'year' ),
		'monthnum'        => get_query_var( 'monthnum' ),
		'day'             => get_query_var( 'day' ),
		'w'               => get_query_var( 'w' ),
	);

	$parsed_args = wp_parse_args( $args, $defaults );

	$post_type_object = get_post_type_object( $parsed_args['post_type'] );
	if ( ! is_post_type_viewable( $post_type_object ) ) {
		return;
	}

	$parsed_args['post_type'] = $post_type_object->name;

	if ( '' === $parsed_args['type'] ) {
		$parsed_args['type'] = 'monthly';
	}

	if ( ! empty( $parsed_args['limit'] ) ) {
		$parsed_args['limit'] = absint( $parsed_args['limit'] );
		$parsed_args['limit'] = ' LIMIT ' . $parsed_args['limit'];
	}

	$order = strtoupper( $parsed_args['order'] );
	if ( 'ASC' !== $order ) {
		$order = 'DESC';
	}

	// This is what will separate dates on weekly archive links.
	$archive_week_separator = '&#8211;';

	$sql_where = $wpdb->prepare( "WHERE post_type = %s AND post_status = 'publish'", $parsed_args['post_type'] );

	/**
	 * Filters the SQL WHERE clause for retrieving archives.
	 *
	 * @since 2.2.0
	 *
	 * @param string $sql_where   Portion of SQL query containing the WHERE clause.
	 * @param array  $parsed_args An array of default arguments.
	 */
	$where = apply_filters( 'getarchives_where', $sql_where, $parsed_args );

	/**
	 * Filters the SQL JOIN clause for retrieving archives.
	 *
	 * @since 2.2.0
	 *
	 * @param string $sql_join    Portion of SQL query containing JOIN clause.
	 * @param array  $parsed_args An array of default arguments.
	 */
	$join = apply_filters( 'getarchives_join', '', $parsed_args );

	$output = '';

	$last_changed = wp_cache_get_last_changed( 'posts' );

	$limit = $parsed_args['limit'];

	if ( 'monthly' === $parsed_args['type'] ) {
		$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 $order $limit";
		$key     = md5( $query );
		$key     = "wp_get_archives:$key:$last_changed";
		$results = wp_cache_get( $key, 'posts' );
		if ( ! $results ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $parsed_args['after'];
			foreach ( (array) $results as $result ) {
				$url = get_month_link( $result->year, $result->month );
				if ( 'post' !== $parsed_args['post_type'] ) {
					$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
				}
				/* translators: 1: Month name, 2: 4-digit year. */
				$text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
				if ( $parsed_args['show_post_count'] ) {
					$parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month;
				$output  .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
			}
		}
	} elseif ( 'yearly' === $parsed_args['type'] ) {
		$query   = "SELECT YEAR(post_date) AS `year`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date) ORDER BY post_date $order $limit";
		$key     = md5( $query );
		$key     = "wp_get_archives:$key:$last_changed";
		$results = wp_cache_get( $key, 'posts' );
		if ( ! $results ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $parsed_args['after'];
			foreach ( (array) $results as $result ) {
				$url = get_year_link( $result->year );
				if ( 'post' !== $parsed_args['post_type'] ) {
					$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
				}
				$text = sprintf( '%d', $result->year );
				if ( $parsed_args['show_post_count'] ) {
					$parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$selected = is_archive() && (string) $parsed_args['year'] === $result->year;
				$output  .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
			}
		}
	} elseif ( 'daily' === $parsed_args['type'] ) {
		$query   = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, DAYOFMONTH(post_date) AS `dayofmonth`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date), DAYOFMONTH(post_date) ORDER BY post_date $order $limit";
		$key     = md5( $query );
		$key     = "wp_get_archives:$key:$last_changed";
		$results = wp_cache_get( $key, 'posts' );
		if ( ! $results ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $parsed_args['after'];
			foreach ( (array) $results as $result ) {
				$url = get_day_link( $result->year, $result->month, $result->dayofmonth );
				if ( 'post' !== $parsed_args['post_type'] ) {
					$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
				}
				$date = sprintf( '%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth );
				$text = mysql2date( get_option( 'date_format' ), $date );
				if ( $parsed_args['show_post_count'] ) {
					$parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$selected = is_archive() && (string) $parsed_args['year'] === $result->year && (string) $parsed_args['monthnum'] === $result->month && (string) $parsed_args['day'] === $result->dayofmonth;
				$output  .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
			}
		}
	} elseif ( 'weekly' === $parsed_args['type'] ) {
		$week    = _wp_mysql_week( '`post_date`' );
		$query   = "SELECT DISTINCT $week AS `week`, YEAR( `post_date` ) AS `yr`, DATE_FORMAT( `post_date`, '%Y-%m-%d' ) AS `yyyymmdd`, count( `ID` ) AS `posts` FROM `$wpdb->posts` $join $where GROUP BY $week, YEAR( `post_date` ) ORDER BY `post_date` $order $limit";
		$key     = md5( $query );
		$key     = "wp_get_archives:$key:$last_changed";
		$results = wp_cache_get( $key, 'posts' );
		if ( ! $results ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		$arc_w_last = '';
		if ( $results ) {
			$after = $parsed_args['after'];
			foreach ( (array) $results as $result ) {
				if ( $result->week != $arc_w_last ) {
					$arc_year       = $result->yr;
					$arc_w_last     = $result->week;
					$arc_week       = get_weekstartend( $result->yyyymmdd, get_option( 'start_of_week' ) );
					$arc_week_start = date_i18n( get_option( 'date_format' ), $arc_week['start'] );
					$arc_week_end   = date_i18n( get_option( 'date_format' ), $arc_week['end'] );
					$url            = add_query_arg(
						array(
							'm' => $arc_year,
							'w' => $result->week,
						),
						home_url( '/' )
					);
					if ( 'post' !== $parsed_args['post_type'] ) {
						$url = add_query_arg( 'post_type', $parsed_args['post_type'], $url );
					}
					$text = $arc_week_start . $archive_week_separator . $arc_week_end;
					if ( $parsed_args['show_post_count'] ) {
						$parsed_args['after'] = '&nbsp;(' . $result->posts . ')' . $after;
					}
					$selected = is_archive() && (string) $parsed_args['year'] === $result->yr && (string) $parsed_args['w'] === $result->week;
					$output  .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
				}
			}
		}
	} elseif ( ( 'postbypost' === $parsed_args['type'] ) || ( 'alpha' === $parsed_args['type'] ) ) {
		$orderby = ( 'alpha' === $parsed_args['type'] ) ? 'post_title ASC ' : 'post_date DESC, ID DESC ';
		$query   = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit";
		$key     = md5( $query );
		$key     = "wp_get_archives:$key:$last_changed";
		$results = wp_cache_get( $key, 'posts' );
		if ( ! $results ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			foreach ( (array) $results as $result ) {
				if ( '0000-00-00 00:00:00' !== $result->post_date ) {
					$url = get_permalink( $result );
					if ( $result->post_title ) {
						/** This filter is documented in wp-includes/post-template.php */
						$text = strip_tags( apply_filters( 'the_title', $result->post_title, $result->ID ) );
					} else {
						$text = $result->ID;
					}
					$selected = get_the_ID() === $result->ID;
					$output  .= get_archives_link( $url, $text, $parsed_args['format'], $parsed_args['before'], $parsed_args['after'], $selected );
				}
			}
		}
	}

	if ( $parsed_args['echo'] ) {
		echo $output;
	} else {
		return $output;
	}
}