single.phpに関連記事を表示させる方法について

single.phpに関連記事を表示させる方法についてまとめます。

## 実装条件

- uncategorizedのカテゴリーに所属する投稿を表示
- ランダムに表示
- 表示中の投稿を除く
- 表示件数は8件

```php
<?php
	$current_post_id = get_the_ID(); //現在の投稿のidを取得
	
		$args = array(
			'post_type' => 'post', //投稿タイプ
			'category_name' => 'uncategorized', //投稿カテゴリ
			'posts_per_page' => 8, //8件表示
			'orderby' => 'rand', //ランダムに
			'post__not_in' => array($current_post_id) //現在の投稿IDを除外
		);

	$the_query = new WP_Query($args);
?>

<?php if ($the_query->have_posts()) : ?>
	<?php while ($the_query->have_posts()) : ?>
		<?php $the_query->the_post(); ?>
		<a class="related-item" href="<?php the_permalink(); ?>">
			<div class="related-item-img">
				<?php if (has_post_thumbnail()) : ?>
					<?php the_post_thumbnail(); ?>
				<?php else : ?>
					<img src="<?php echo get_template_directory_uri(); ?>/img/noimg.png" alt="">
				<?php endif; ?>
			</div><!-- /related-item-img -->
				<div class="related-item-title"><?php the_title(); ?></div><!-- /related-item-title -->
		</a><!-- /related-item -->
	<?php endwhile; ?>
	<?php wp_reset_postdata(); ?>
<?php endif; ?>
```

## 現在の投稿IDを取得

```php
$current_post_id = get_the_ID(); //現在の投稿のidを取得
```

`get_the_ID()` 関数は、現在の投稿（記事やページなど）のIDを取得します。これは後でクエリの条件として、現在の投稿を結果から除外するのに使用されます。

## WP_Query クラスを使ったカスタムクエリの設定

```php
	
$args = array(
	'post_type' => 'post', //投稿タイプ
	'category_name' => 'uncategorized', //投稿カテゴリ
	'posts_per_page' => 8, //8件表示
	'orderby' => 'rand', //ランダムに
	'post__not_in' => array($current_post_id) //現在の投稿IDを除外
);

$the_query = new WP_Query($args);	
```

この部分でカスタムクエリの条件を設定しています。`$args` 配列内のパラメータは以下のような意味になっています。

- `post_type` : 投稿タイプを指定します。ここでは標準の投稿タイプ「post」が指定されています。
- `category_name` : 表示する投稿のカテゴリーを指定します。ここでは「uncategorized」というカテゴリー名が指定されています。
- `posts_per_page` : 一度に表示する投稿の数を指定します。ここでは8つの投稿が指定されています。
- `orderby` : 投稿の並べ替え基準を指定します。「rand」はランダムな順序を意味します。※`date` がデフォルト。`date` は投稿の公開日に基づいて並べ替えます。最新の投稿が最初にくる。
- `post__not_in` : この配列内の投稿IDを結果から除外します。ここでは現在の投稿IDを除外しています。

### ※point

```php
$the_query = new WP_Query($args);
```

この行は、`WP_Query`クラスを使用してカスタムクエリを作成しています。

1. インスタンス化：`new WP_Query()` は、`WP_Query` クラスの新しいインスタンスを作成します。これにより、カスタムクエリの準備が整います。
2. 数の渡し方: `$args`は、このクエリのパラメーターを含む配列です。この配列には、取得したい投稿の種類、数、並べ替え順序、フィルター条件などが指定されます。例えば、特定のカテゴリーの投稿だけを取得したり、投稿をランダムに取得したり、特定のタグを持つ投稿を除外したりすることができます。
3. クエリの実行: このコード行が実行されると、指定された条件に基づいてデータベースが検索され、結果が`$the_query`オブジェクトに格納されます。

`WP_Query`を使用する主な理由は、WordPressのメインクエリ（通常は現在のページに自動的に適用されるクエリ）に影響を与えずに、追加のクエリを実行する能力を提供することにあります。これにより、特定のページやテンプレートファイル内で特定の条件に基づく追加の投稿リストを表示することが可能になります。

## カスタムループの実行と表示

```php
if ($the_query->have_posts()) :
	while ($the_query->have_posts()) : $the_query->the_post();
```

`if ($the_query->have_posts()) :`は、カスタムクエリ `the_query` が1つ以上の投稿をもっているかどうかをチェックします。 `have_posts` メソッドは、クエリが返す投稿リストにまだ処理していない投稿が存在する場合 `true` を返します。つまり、この条件は「指定された条件にマッチする投稿が1つでも存在するか？」を確認しています。

`while ($the_query->have_posts()) : $the_query->the_post();` は、 `have_posts()` メソッドを用いて処理する投稿がまだ残っているかを確認し続けます。ループの各イテレーションで`the_post()`メソッドが呼ばれ、`$the_query`によって指定された次の投稿をセットアップします。

※イテレーション（iteration）：プログラミングにおいて、繰り返し処理やループ処理の一回分の実行を指します。

## **グローバル変数$postのリセット**

```php
wp_reset_postdata();
```

カスタムクエリによって変更された現在の投稿データ（グローバル変数`$post`の内容）を、カスタムクエリ実行前のオリジナルの状態に戻します。

WordPressでは、カスタムクエリ（`WP_Query`オブジェクトを使ったクエリ）を実行すると、そのクエリによって取得された投稿のデータでグローバル変数`$post`が上書きされます。これは、カスタムクエリ内でループ処理する際に、テンプレートタグ（例: `the_title()`や`the_content()`）が正しく現在処理中の投稿のデータを参照できるようにするためです。しかし、この変更はカスタムクエリが終了した後も残り、その後のコードで予期せぬ影響を及ぼす可能性があります。

`wp_reset_postdata();`を実行することで、カスタムクエリのループが終了した後に`$post`を元の状態（カスタムクエリを実行する前に参照されていた投稿のデータ）に戻します。これにより、カスタムクエリの後に実行されるテンプレートタグやその他のコードが、正しい投稿データを参照することが保証されます。

つまり、`wp_reset_postdata();`は「カスタムクエリ後の片付け」として非常に重要で、データの整合性を保つために必要な処理です。