制作会社から制作会社じゃない会社に転職が決まりました。制作会社で学んだことを残らず記事にしたいと思います。

パンDKOTORI Blogの公式キャラクター「パンD」です。
コーディングWordPress「wp_get_archives()」で出力されるHTMLタグをカスタマイズ[WordPress]

「wp_get_archives()」で出力されるHTMLタグをカスタマイズ[WordPress]

2014年12月13日WordPress 便利コード PHP 
「wp_get_archives()」で出力されるHTMLタグをカスタマイズ[WordPress]記事のアイキャッチ画像

「wp_get_archives()」で出力されるHTMLタグを徹底的にカスタマイズする方法を紹介します。

まえがき

今回の記事では、月別アーカイブリストを出力してくれるタグ「wp_get_archives()」で出力されるHTMLタグを徹底的にカスタマイズする方法をご紹介します。
この「wp_get_archives()」タグはパラメータで「format」というものが用意されており、個々のリンクをリスト形式(liタグ)で囲ったりセレクトボックス(optionタグ)で囲ったりということは制御できるんですが、それしかできない!!

「wp_get_archives()」で普通に出力されるコードはこんな感じです。

<li><a href="http://kotori-blog.com/2014/12/">2014年12月</a>(5)</li>
<li><a href="http://kotori-blog.com/2014/11/">2014年11月</a>(2)</li>

コード上の「(5)」とかは記事数ですね。

では、お困りシチュエーションの具体例を挙げてみると
記事数もaタグ内に含めたいと思っても対応できません
それと
aタグの内側にspanとか付けたいと思っても対応できません

まぁかなりマニアックなシチュエーションではあるのですがw
解決していきましょう。

「functions.php」に関数を定義しなおすことで出力結果を自在にカスタマイズします。

「functions.php」に「wp_get_archives()」関数をコピーする

そもそも関数の出力結果を変えたいなら、その関数が定義されているコアファイルを弄ってしまえば良いのです。
が、コアファイル弄るとWordPressをバージョンアップした際に編集済みファイルが新しいファイルに上書きされ編集内容が消えてしまい結果的に元に戻ってしまいます。
それを回避するため「functions.php」に新しい関数として「wp_get_archives()」を定義するのです。

「wp_get_archives()」が定義されているのは wp-includes/general-template.php1186行目です。(WordPress4.01)
見つからない場合はコードを「wp_get_archives」で検索かけてみてください。

実際に「wp_get_archives()」関数の中身を確認すると分かるのですが、「wp_get_archives()」関数は処理の途中で「get_archives_link()」関数をところどころで呼び出しています。

「get_archives_link()」関数はドコで定義されているかというと「wp_get_archives()」関数の直ぐ上です。

ということで「wp_get_archives()」「get_archives_link()」をコピーして関数名を変更して「functions.php」に追加します。

実際にKoToRiが使用したコードを晒します。
下記コードをそのまま「functions.php」にペーストしてください。
因みに結構長いです。

function get_archives_link2($url, $text, $format = 'html', $before = '', $after = '') {
	$text = wptexturize($text);
	$url = esc_url($url);

	if ('link' == $format)
		$link_html = "\t<link rel='archives' title='" . esc_attr( $text ) . "' href='$url' />\n";
	elseif ('option' == $format)
		$link_html = "\t<option value='$url'>$before $text $after</option>\n";
	elseif ('html' == $format)
		$link_html = "\t<li>$before<a href='$url'>$text</a>$after</li>\n";
	else // custom
		$link_html = "\t$before<a href='$url'>$text</a>$after\n";

	/**
	 * Filter the archive link content.
	 *
	 * @since 2.6.0
	 *
	 * @param string $link_html The archive HTML link content.
	 */
	$link_html = apply_filters( 'get_archives_link', $link_html );

	return $link_html;
}




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

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

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

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

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

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

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

	// 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' );
	}

	/**
	 * Filter 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  $r         An array of default arguments.
	 */
	$where = apply_filters( 'getarchives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $r );

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

	$output = '';

	$last_changed = wp_cache_get( 'last_changed', 'posts' );
	if ( ! $last_changed ) {
		$last_changed = microtime();
		wp_cache_set( 'last_changed', $last_changed, 'posts' );
	}

	$limit = $r['limit'];

	if ( 'monthly' == $r['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";
		if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $r['after'];
			foreach ( (array) $results as $result ) {
				$url = get_month_link( $result->year, $result->month );
				/* translators: 1: month name, 2: 4-digit year */
				$text = sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $result->month ), $result->year );
				if ( $r['show_post_count'] ) {
					$r['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$output .= get_archives_link2( $url, $text, $r['format'], $r['before'], $r['after'] );
			}
		}
	} elseif ( 'yearly' == $r['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";
		if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $r['after'];
			foreach ( (array) $results as $result) {
				$url = get_year_link( $result->year );
				$text = sprintf( '%d', $result->year );
				if ( $r['show_post_count'] ) {
					$r['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$output .= get_archives_link2( $url, $text, $r['format'], $r['before'], $r['after'] );
			}
		}
	} elseif ( 'daily' == $r['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";
		if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
			$results = $wpdb->get_results( $query );
			$cache[ $key ] = $results;
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			$after = $r['after'];
			foreach ( (array) $results as $result ) {
				$url  = get_day_link( $result->year, $result->month, $result->dayofmonth );
				$date = sprintf( '%1$d-%2$02d-%3$02d 00:00:00', $result->year, $result->month, $result->dayofmonth );
				$text = mysql2date( $archive_day_date_format, $date );
				if ( $r['show_post_count'] ) {
					$r['after'] = '&nbsp;(' . $result->posts . ')' . $after;
				}
				$output .= get_archives_link2( $url, $text, $r['format'], $r['before'], $r['after'] );
			}
		}
	} elseif ( 'weekly' == $r['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";
		if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		$arc_w_last = '';
		if ( $results ) {
			$after = $r['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( $archive_week_start_date_format, $arc_week['start'] );
					$arc_week_end   = date_i18n( $archive_week_end_date_format, $arc_week['end'] );
					$url            = sprintf( '%1$s/%2$s%3$sm%4$s%5$s%6$sw%7$s%8$d', home_url(), '', '?', '=', $arc_year, '&amp;', '=', $result->week );
					$text           = $arc_week_start . $archive_week_separator . $arc_week_end;
					if ( $r['show_post_count'] ) {
						$r['after'] = '&nbsp;(' . $result->posts . ')' . $after;
					}
					$output .= get_archives_link2( $url, $text, $r['format'], $r['before'], $r['after'] );
				}
			}
		}
	} elseif ( ( 'postbypost' == $r['type'] ) || ('alpha' == $r['type'] ) ) {
		$orderby = ( 'alpha' == $r['type'] ) ? 'post_title ASC ' : 'post_date DESC ';
		$query = "SELECT * FROM $wpdb->posts $join $where ORDER BY $orderby $limit";
		$key = md5( $query );
		$key = "wp_get_archives:$key:$last_changed";
		if ( ! $results = wp_cache_get( $key, 'posts' ) ) {
			$results = $wpdb->get_results( $query );
			wp_cache_set( $key, $results, 'posts' );
		}
		if ( $results ) {
			foreach ( (array) $results as $result ) {
				if ( $result->post_date != '0000-00-00 00:00:00' ) {
					$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;
					}
					$output .= get_archives_link2( $url, $text, $r['format'], $r['before'], $r['after'] );
				}
			}
		}
	}
	if ( $r['echo'] ) {
		echo $output;
	} else {
		return $output;
	}
}

関数名はそれぞれ「wp_get_archives2()」「get_archives_link2()」としてあります。

「wp_get_archives()」で出力されるHTMLコードを制御している「get_archives_link()」関数を編集する

「wp_get_archives2()」「get_archives_link2()」を「functions.php」に追加できたら、実際に出力されるHTMLタグを編集します。
具体的にドコを編集するかというと「get_archives_link2()」関数を編集します。

下記コードのハイライト部分が出力されるHTMLコードを指定している箇所になります。

function get_archives_link2($url, $text, $format = 'html', $before = '', $after = '') {
	$text = wptexturize($text);
	$url = esc_url($url);

	if ('link' == $format)
		$link_html = "\t<link rel='archives' title='" . esc_attr( $text ) . "' href='$url' />\n";
	elseif ('option' == $format)
		$link_html = "\t<option value='$url'>$before $text $after</option>\n";
	elseif ('html' == $format)
		$link_html = "\t<li>$before<a href='$url'>$text</a>$after</li>\n";
	else // custom
		$link_html = "\t$before<a href='$url'>$text</a>$after\n";

	/**
	 * Filter the archive link content.
	 *
	 * @since 2.6.0
	 *
	 * @param string $link_html The archive HTML link content.
	 */
	$link_html = apply_filters( 'get_archives_link', $link_html );

	return $link_html;
}

「wp_get_archives()」のデフォルトのフォーマットは「html」形式なので10行目に書かれているHTMLタグ部分を編集します。

「wp_get_archives()」で出力されるHTMLコードの編集例

それではこの記事のまえがきで挙げたシチュエーションに対応するコードを挙げていきます。それぞれ上記コードの10行目を編集してくださいね。

記事数もaタグ内に含めたい

記事数もaタグ内に含めたいなら「$after」を「</a>」の内側にいれるだけです。

		$link_html = "\t<li>$before<a href='$url'>$text$after</a></li>\n";

aタグの内側にspanとか付けたい

この場合は普通に追加したいHTMLコードを書きます。

		$link_html = "\t<li>$before<a href='$url'><span>$text<span></a>$after</li>\n";

他にも「wp_get_archives()」のパラメータ「before」をaタグ内に入れたい場合なんかも「$before」変数をaタグの内側に入れてやるだけで対応できます。
好きなように編集してください。

追加した「wp_get_archives2()」関数の出力

肝心の出力ですが、何も難しいことはありません。
実際に表示したい場所に下記コードを追加するだけです。

<?php wp_get_archives2('type=monthly'); ?>

「type=monthly」となってますが、この辺はオリジナルの「wp_get_archives()」と全く同じパラメータを使用できるので適宜変更してください。
ただ、「format」パラメータは指定しないでください。
「get_archives_link2()」で編集したHTMLコードは「format」パラメータが「html」の時に出力されるコードになります。
「format」パラメータは何も指定しないと勝手に「html」になります。

まとめ

若干メンドクサイ方法ではありますがHTMLコードを好きなようにカスタマイズできるという点では問題ないかと思います。

実際に「wp_get_archives()」で出力されるaタグの内側にspanタグを入れたいって思った時にGoogleで色々検索したのですが有力な情報が出てきませんでした。
ただ、パラメータに「show_post_count=1」を指定して出力される記事数をaタグ内に含める方法は出てきて、それがバリバリの正規表現だったのです。
ぶっちゃけ今回の場合も正規表現を駆使すれば、わざわざコアファイルからオリジナル関数を引っ張ってこなくても対応できたのではないかと思います。
しか~し!KoToRiは正規表現は全くダメなのです><

ハッキリいって今回紹介した方法が最善の方法とは思っておりませんw

なので誰かもっとスマートな方法を知っていたら是非とも教えてください。

シェアするみんなシェアしてね

フォローするフォローする

いつもKOTORI Blogをご覧いただきありがとうございます。Facebook、Twitterを通じて、皆様と交流していき色んな情報を共有していければな~と思ってます。お気軽に登録してください!

基本フォロー返します。

RSSを登録する

RSSはこちらから。

follow us in feedly

Feedly使ってる人はこちらから。

Buy me a Beer

動く!パンDのLINEスタンプ
好きな人にアプローチスタンプ
パンDのLINEスタンプ

関連する記事関連する記事も読んでみてね

コメント

  • 田中

    いつも分かり易く解説していただいてありがとうございます。こちらのコードで思うとおりに票田できました。一つだけ記事の件数前後に()がありますが、こちらを削除する方法ご存知ございませんでしょうか。お教えいただけタラと思いご連絡させていただきました。何卒よろしくお願いします。

    • kotoriblog

      田中さん
      コメントありがとうございます!
      未検証なのですが、functions.phpに追加するコードのところどころにある
      $r[‘after’] = ‘ (‘ . $result->posts . ‘)’ . $after;

      $r[‘after’] = ‘ ‘ . $result->posts . ” . $after;
      直せばいけると思います!