ワイヤード・パンチ

元・大阪人が、岡山の山奥でも生きていけることを証明するためのブログ。

WordPressで、記事タイトルとカスタムフィールドのどちらかに、キーワードが部分一致するものを検索する方法。

WordPressのだいたいのテーマには、キーワード検索の機能が備わっています。

しかし、その検索の対象になるのは、通常ならば各記事のタイトルおよび本文のみであり、カスタムフィールドは対象になりません。

今回、タイトルとカスタムフィールドどちらかにキーワードを含んでいるものを出したいので、そのための対処法。

広告

そもそも検索ボックスを作るには?

<!-- 標準の投稿タイプの場合 -->
<form method="get" action="<?php echo home_url(); ?>">
	<input type="text" name="s">
	<button type="submit">検索</button>
</form>

<!-- カスタム投稿タイプの場合 -->
<form method="get" action="<?php echo get_post_type_archive_link("投稿タイプのスラッグ"); ?>">
	<input type="text" name="s">
	<button type="submit">検索</button>
</form>

上記のような入力フォームをテーマ上のどこかに置いて、検索を実行すれば、キーワード検索が可能になります。

キーワード検索を行うためには、nameが「s」の入力ボックスが必要です。

「s」以外ではキーワード検索になりません。

通常だとタイトルとカスタムフィールドの両方は検索できない。

add_action("pre_get_posts", function ($query) {
	if(is_search()) {
		$meta_query = [
			"relation" => "AND",
			[
				"key" => "検索用フィールド",
				"value" => filter_input(INPUT_GET, "s"),
				"compare" => "LIKE",
			],
		];
		$query->set("meta_query", $meta_query);
	}
	return $query;
});

functions.phpに、上記のようなフックを作成すれば、キーワード検索のページに入ったときに、カスタムフィールドも検索対象になります。

pre_get_postsは検索結果に影響を与えるフックであり、meta_queryはカスタムフィールドの条件となります。

しかし上記のコードの場合、タイトルとカスタムフィールドどちらにもキーワードが含まれていないと、ヒットしません。

add_action("pre_get_posts", function ($query) {
	if(is_search()) {
		$meta_query = [
			"relation" => "AND",
			[
				"key" => "検索用フィールド",
				"value" => filter_input(INPUT_GET, "s"),
				"compare" => "LIKE",
			],
		];
		$query->set("meta_query", $meta_query);
		$query->set("s", "");
	}
	return $query;
});

それならばと、今度は「$query->set(“s”, “”)」を加えます。

検索キーワードである「s」を、強制的に空欄に書き換えています。

ちゃんとキーワードを入れても、キーワードなしで検索したことと同じになります。

でもmeta_queryには「filter_input(INPUT_GET, “s”)」があるので、こちらはキーワードを入れたことになります。

ただしこれで実行した場合、タイトルは全く検索対象にならず、カスタムフィールドだけが検索対象になってしまいます。

カスタムフィールドにタイトルも入れることで解決。

調べ物を続けてみましたが、どうしても通常の方法では、タイトルかカスタムフィールドどちらかにキーワードを含んでいるものを検索する、ということができませんでした。

よってここは、タイトルの値とカスタムフィールドの値の両方を参照するという方法はやめます。

タイトルの検索は無効化して、カスタムフィールドのみを検索対象とします。

つまり、コードとしては先程の後者のコードになります。

でもそうすると、タイトルは検索対象にならないから意味ないのでは?

と思われそうですが、そこは検索対象用のカスタムフィールドを新たに作成することで解決します。

add_action("save_post", function($post_id) {
	if(get_post_type() === "post") {
		$output = filter_input(INPUT_POST, "post_title") . "/" . get_field("タイトルとともに検索対象にしたいフィールド", $post_id);
		update_post_meta($post_id, "検索用フィールド", $output);
	}

あらかじめカスタムフィールドを1つ作り、save_postフックを作って、記事編集の保存時にカスタムフィールドも自動的に保存されるようにします。

このカスタムフィールドには自動的に、タイトルおよび別のカスタムフィールドがくっついた文字列が入ることになります。

このカスタムフィールドを検索対象にすることで、タイトルかカスタムフィールドどちらかにキーワードを含むものを探す、という検索が可能になるでしょう。

なお、上記のコードは「Advanced Custom Fields」というプラグインでカスタムフィールドを作成した場合のコードであり、get_fieldはプラグイン専用の関数となります。

プラグインを使っていない、あるいはget_fieldを使いたくない場合は、下記のコードになるでしょう。

add_action("save_post", function($post_id) {
	if(get_post_type() === "post") {
		$output = filter_input(INPUT_POST, "post_title") . "/" . get_post_meta($post_id, "タイトルとともに検索対象にしたいフィールド", true);
		update_post_meta($post_id, "検索用フィールド", $output);
	}

また、save_postで自動的にカスタムフィールドの値を保存しなくても、手動で検索用フィールドの値を書き換えられないことはありません。

ただ、記事のタイトルやカスタムフィールドを変えるたびに、いちいち検索用フィールドを変えるのも面倒だったので、save_postを使うことにしています。

これで、保存するたびに自動的に検索用フィールドも更新されます。