WordPressショートコード｜年別・年度別で記事一覧を表示｜WP_Queryの使用例

WordPressで、年数別で投稿記事の一覧を表示させたい、それをショートコードで実装したいと思い、その実装方法を先日に投稿しました。

旧記事：[WordPress｜ショートコード｜WP_Queryで投稿一覧を表示](https://qiita.com/tomokei5634/items/1b1ba9eee3b1dee282df)

しかし読み返すと、いくつかの課題を抱えたものでした。
本記事は、[旧記事](https://qiita.com/tomokei5634/items/1b1ba9eee3b1dee282df)の訂正版です。

# 本記事のコードの特徴
* `get_posts()` ではなく、 `WP_Query（）` を用いています。
* **ショートコード**での実装となります。

# 実装手順
## 1）functions.phpへコードの追加
下記のコードを、使用中のWordPressテーマの`functions.php`内へ追加してください。

```php:functions.php
function getPostList($atts)
{

	$args = [
		'post_type' => 'post',
		'posts_per_page' => '-1',
		'orderby' => 'meta_value',
		'order' => 'DESC'
	];

	if ($atts['category']) {
		$args += ['category__in' => explode(',', $atts['category'])];
	}

	if ($atts['tag']) {
		$args += ['tag__in' => explode(',', $atts['tag'])];
	}

	if ($atts['year']) {
		$args += ['year' => $atts['year']];
	}

	$wp_query = new WP_Query($args);
	$outPut = '';
	if ($wp_query->have_posts()) {
		$year = null;
		$outPut .= '<div class="PostList"><ul>' . PHP_EOL;
		while ($wp_query->have_posts()) {
			$wp_query->the_post();
			if ($year != get_the_date('Y')) {
				$year = get_the_date('Y');
				$outPut .= '<li id="PostListId_' . $year . '" class="PostList_title">' . $year . '</li>' . PHP_EOL;
			}
			$date = get_the_date('Y-m-d');
			$cats = get_the_category();
			$cats_outPut = '';
			if ($cats) {
				foreach ($cats as $category) {
					$cats_outPut .= '<span>' . $category->cat_name . '</span>';
				}
			}
			$tags = get_the_tags();
			$tags_outPut = '';
			if ($tags) {
				foreach ($tags as $tag) {
					$tags_outPut .= '<span>' . $tag->name . '</span>';
				}
			}
			$outPut .= '<li id="PostId_' . get_the_ID() . '" class="Post_item">';
			$outPut .= '<a href="' . esc_url(get_permalink()) . '" class="Post_link"><div class="Post_body">';
			$outPut .= '<div class="Post_meta">';
			$outPut .= '<div class="Post_time"><time datetime="' . $date . '">' . $date . '</time></div>';
			$outPut .= '<div class="Post_category">' . $cats_outPut . '</div>';
			$outPut .= '<div class="Post_tag">' . $tags_outPut . '</div>';
			$outPut .= '</div>';
			$outPut .= '<div class="Post_title">' . get_the_title() . '</div>';
			$outPut .= '</div></a>';
			$outPut .= '</li>' . PHP_EOL;
		}
		$outPut .= '</ul></div>' . PHP_EOL;
	}

	wp_reset_postdata();
	return $outPut;
}
add_shortcode("PostList", "getPostList");
```

## 2）記事中へショートコードの追加
任意の記事（ページ）にショートコードを設置してください。
ショートコードは `[PostList]` です。

![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_283603_8bce6540-2bb0-b268-9020-d82847649f11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/4843b3f6-154a-558e-810c-e8b947b8872e.png)

以上です。

## 設置時の出力HTML
こんな感じのHTMLが出力されます。
<img width="625" alt="スクリーンショット 2020-03-24 11.56.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/c98b9998-9d3a-9f2a-cb44-1a4cbd2eec47.png">

# オプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283603/7716acbd-5459-b5b3-31ea-3fe56573111a.png)

ショートコードへ引数を渡し、表示させる投稿を絞り込むことができます。
（現状は年・カテゴリ・タグで絞り込めます。カテゴリ・タグはIDを配列で複数渡すことができます）

絞り込む項目を変更したい場合は、この辺りを変更してください。
↓

```php:functions.php（一部）
	$args = [
		'post_type' => 'post',
		'posts_per_page' => '-1',
		'orderby' => 'meta_value',
		'order' => 'DESC'
	];

	if ($atts['category']) {
		$args += ['category__in' => explode(',', $atts['category'])];
	}

	if ($atts['tag']) {
		$args += ['tag__in' => explode(',', $atts['tag'])];
	}

	if ($atts['year']) {
		$args += ['year' => $atts['year']];
	}
```

絞り込む項目については、次のサイトが参考になります。
【参考サイト】[これは便利！WordPressのWP_Queryでよく使うコードスニペット](https://sole-color-blog.com/blog/265/)
【参考サイト】[関数リファレンス/WP Query](https://wpdocs.osdn.jp/関数リファレンス/WP_Query)

# 反省点
[旧記事](https://qiita.com/tomokei5634/items/1b1ba9eee3b1dee282df)からの反省点（変更点）を記します。

旧記事：[WordPress｜ショートコード｜WP_Queryで投稿一覧を表示](https://qiita.com/tomokei5634/items/1b1ba9eee3b1dee282df)

## 日付（日時）の取得は get_the_date()
当初は`the_time（）`を用いて日付を取得していましたが、なんか変な挙動をしていました。
`get_the_date()`へ変更すると、万事OKでした。

## ショートコード内の関数は return で返す
ドキュメント**[ショートコード API#出力](https://wpdocs.osdn.jp/ショートコード_API#Output)**にも記載されています。

<blockquote>
ショートコードハンドラー関数の返り値はショートコードマクロの代わりに投稿コンテンツの出力へ挿入されます。 echo ではなく return を使うようにしてください。echo されたものはすべてブラウザへ出力されますが、ページの適切な箇所に表示されません。
</blockquote>

そこで、`echo`で出力していたものを、今回は変数`$outPut`を用意して、その中へ出力したいHTMLを追加していき最後に`return $outPut`で返すようにしました。