BLOG

ブログ

programming

マルチサイトの横断検索に対応する方法【WordPress】

こんにちは、ティウェブ藤園です。

今回は、WordPressのマルチサイトで、デフォルトの検索機能をカスタマイズして、複数サイトの横断検索に対応する方法をご紹介します。

💡 マルチサイトとは、WordPressの機能のひとつで、1つのWordPressの中に複数のサイトを作成することができるものです。
重複する機能やデザインがあったり、今回のように横断検索をしたい場合や、一部のディレクトリにだけ認証機能などを設けたい場合にも便利です。
マルチサイトの作り方や設定方法はこちらをご確認ください。
・WordPress.org | ネットワークの作成
https://ja.wordpress.org/support/article/create-a-network/

目次

検索フォーム

まず、検索フォームを設置します。

<?php get_search_form(); ?>

機能によっては上記のデフォルトの関数で十分なこともありますが、必要であれば下記のようにHTMLで直接記述することもあります 。

<form role="search" method="get" action="<?php echo home_url( '/' ); ?>">
	<input type="text" value="<?php the_search_query(); ?>" name="s" placeholder="キーワード検索">
	<button type="submit">検索</button>
</form>

検索結果ページテーマファイル

WordPressの検索結果ページは、「https://ドメイン名/?s=入力した検索キーワード」で表示されます。

この検索結果ページには、テーマファイル内のsearch.phpが適用されますので、search.phpがある場合はそのファイルをカスタマイズし、search.phpがない場合は新しくsearch.phpを作る必要があります。

<?php
	// キーワード取得
	$s = $_GET['s'];
	$arg = array(
		's' => $s,
	);
	$the_query = new WP_Query($arg);
?>
<?php if($the_query->have_posts()): while($the_query->have_posts()): $the_query->the_post(); ?>

...記事のループ内容...

<?php endwhile; endif; ?>
<?php wp_reset_postdata(); ?>

通常であれば、上記の内容でループ部分は完成します。(これはサブループを使用した形なので、ページャーを使用する場合はまた別の設定が必要になります)

上記の基本の形に記述を追加すると、マルチサイトでの複数サイトの横断検索が可能になります。

マルチサイトの複数サイトの横断検索への対応

それでは、今回の本題に入ります。

完成形

早速ですが、search.phpの完成形は下記の通りです。

<?php
	// 検索キーワードで記事を絞り込む
	$s = $_GET['s'];
	$arg = array(
		's' => $s,
	);
	$the_query = new WP_Query($arg);

	// サイトの情報を配列で取得
	$my_blogs = get_sites();

	// 検索結果を配列にまとめる
	$postsNum = 0;
	foreach ( $my_blogs as $my_blog ) {
		switch_to_blog($my_blog->blog_id);
		$the_query = new WP_Query($arg);
		if ($the_query->have_posts()){
			while($the_query->have_posts()){
				$the_query->the_post();
				$postsNum++;
				$thumbnail = get_the_post_thumbnail_url(get_the_ID(),'large','');
				$postList[get_the_title() . get_the_ID()] = array(
					'title' => get_the_title(),
					'image' => $thumbnail,
					'url' => get_the_permalink(),
				);
			}
		}
		restore_current_blog();
	}
?>
<?php if(!empty($postList)): ?>
<p>該当する記事は<?php echo $postsNum; ?>件です。</p>
<ul>
<?php foreach ( $postList as $index => $postItem ): ?>
	<li>
		<a href="<?php echo $postItem['url']; ?>">
			<?php if(!empty($postItem['image'])): ?>
				<img src="<?php echo $postItem['image']; ?>" alt="" decoding="async" loading="lazy">
			<?php endif; ?>
			<p><?php echo $postItem['title']; ?></p>
		</a>
	</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>該当する記事は見つかりませんでした。</p>
<?php endif; ?>

最上部の$arg内に条件を追加すれば、さまざまな条件検索にも対応が可能です。

以下で詳細を説明します。

各サイトのidを配列で取得する

完成形の10行目で、各子サイトのidを配列で取得しています。

$my_blogs = get_sites();

get_sites()ですべてのサイトの情報を取得することができます。
この関数では、除外するサイトを設定することもできるので、特定のサイトの記事は検索対象から除外したい場合などは適宜条件を追加してください。

検索結果を配列「$postList」にまとめる

取得したサイトのidをもとに、それぞれのサイト内の記事を検索し、「$postList」というひとつの配列にまとめます。

$postsNum = 0; // 検索結果がなければ空とする
foreach ( $my_blogs as $my_blog ) { // 各サイトごとにループを開始
	switch_to_blog($my_blog->blog_id); // 参照元をループのはじまったサイトに切り替える
	$the_query = new WP_Query($arg); // ループ内容を初めに定義した検索条件に指定する
	if ($the_query->have_posts()){
		while($the_query->have_posts()){
			$the_query->the_post();
			$postsNum++; // $postsNumのカウントを1追加する
			$thumbnail = get_the_post_thumbnail_url(get_the_ID(),'large','');
			$postList[get_the_title() . get_the_ID()] = array( // 配列にそれぞれの情報を格納
				'title' => get_the_title(),
				'image' => $thumbnail,
				'url' => get_the_permalink(),
			);
		}
	}
	restore_current_blog(); // 参照元の切り替えをリセットする
}

配列「$postList」をもとに検索結果を表示

<?php if(!empty($postList)): ?>
<p>該当する記事は<?php echo $postsNum; ?>件です。</p>
<ul>
<?php foreach ( $postList as $index => $postItem ): ?>
	<li>
		<a href="<?php echo $postItem['url']; ?>">
			<?php if(!empty($postItem['image'])): ?>
				<img src="<?php echo $postItem['image']; ?>" alt="" decoding="async" loading="lazy">
			<?php endif; ?>
			<p><?php echo $postItem['title']; ?></p>
		</a>
	</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<p>該当する記事は見つかりませんでした。</p>
<?php endif; ?>

配列の中身をもっとカスタマイズすれば、公開日時順やタイトル順での並び替えへの対応なども可能で、カスタムフィールドの値も配列内に含めることが可能です。

余談

今回私が使用した際、下記のようにカスタムタクソノミーの特定のスラッグに検索対象を限定するという条件を含めていました。

$s = $_GET['s'];
$arg = array(
	's' => $s,
	'tax_query' => array(
		array(
			'taxonomy' => 'category',
			'field' => 'slug',
			'terms' => 'news',
		),
		array(
			'taxonomy' => 'custom-taxonomy',
			'field' => 'slug',
			'terms' => 'custom-term',
		),
		'relation' => 'AND',
	),
);
$the_query = new WP_Query($arg);

上記の場合、categoryはデフォルトでマルチサイト内のすべてのサイトに含まれているのでうまく機能したのですが、custom-taxonomyは子サイトにのみ適用し、親サイトでは設定されていないカスタムタクソノミーだったため親サイトで検索した際に検索結果なしという状態に……

検索機能にカスタムタクソノミーを利用する際は、その検索機能を使用するすべてのサイトでカスタムタクソノミーを設定すると、きちんと動作するようになります!

まとめ

WordPressの検索フォームは手軽にサイト内検索を設置できる便利なものですが、なかなかカスタマイズが難しく、また、扱いにくいです。

今回は、マルチサイトの横断検索に関してはネット上でも情報が古いものが多く、実装にあたってなかなか困難な部分が多かったため、備忘録も兼ねて、技術共有のブログといたしました。

ティウェブでは上記のような、部分的で複雑なカスタマイズなども承っておりますので、お気軽にお問い合わせ・ご相談ください。

その他のWordPressの記事