【PHP】検索文字列をハイライトさせる簡単な方法

プログラミング

どうも、コウイチです。

今回は、テキストボックスに文字列を入力すると、対象の文章にヒットした部分をハイライト(強調表示)させる機能を、PHPで実装してみたいと思います。

ヒットした文字列を黄色い蛍光ペンで塗ってみます。

作りたい機能

以下の機能を作ります。

検索画面

検索画面です。検索窓にキーワードを入力して、エンターか検索ボタンをクリックすると、下のサンプル文章に対して検索をかけ、ヒットしたらその部分を黄色くハイライトさせる。

それだけではつまらないので、あいまい検索を可能にしてみた

あいまい検索も可能にしてみました。

ただ検索するだけではなくて、多少のあいまいな検索にもヒットするように。

たとえば、

ひらがなでもカタカナでも、半角でも全角でも、大文字でも小文字でも、違いを無視してヒットさせるようにしました。

変換をミスったりするユーザーもいますし、半角全角の違いでヒットしないとなると結構不便です。

Google先生のような超高性能な「もしかして」機能は難しいですが、素人でも簡単なコードである程度はやれます。

ソースコードと解説

それでは完成形のサンプルコードをどうぞ。解説付きです。

作るファイルは、

  • index.php(メインファイル)
  • lib.php(ライブラリファイル)

の2つです。

index.php

メインのPHPです。

<?php

// 【PHP】検索文字列をハイライトさせる簡単な方法

// ライブラリをインポート
require_once('lib.php');

// 検索される文字列
$target_string = <<< EOM
この本に向いているのはこんな人!<br>
さて、この本はどんな人に向いてそうか、考えてみました。<br><br>

入門書って、読みやすいけど面白いものが作れないからつまらない。<br>
面白いもの作ってみたいけど、たいてい難しい本ばかりで挫折してきた。<br>
楽してプログラミング中級者を名乗りたい<br><br>

といった、勉強したくないけど上達したい!というワガママなあなたにはピッタリです笑<br>
大丈夫、この本を実践し読み終わったころには、自動的に知識がついています。<br>
その後は、中級者向けの本にもすんなり入っていけるようになっているはずです。<br>
是非この本で、プログラミング中級者の仲間入りをしてください!
EOM;

// 検索する文字列をPOSTで受信する。
$search_string = '';
if(isset($_POST['search_string'])){
	$search_string = htmlspecialchars($_POST['search_string'], ENT_QUOTES, 'UTF-8');
}

// 検索される文字列から検索する文字列を検索し、見つかったらハイライトする。
$result_string = search_highlight($search_string, $target_string);

?>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9" />

<title>【PHP】検索文字列をハイライトさせる簡単な方法</title>

</head>

<body>

<h1>【PHP】検索文字列をハイライトさせる簡単な方法</h1>

<p>
キーワードを入力して検索してください。
</p>

<form name="search_form" method="POST" action=".">
<input type="text" name="search_string"><input type="submit" value="検索">
</form>

<p>検索キーワード:<?php print $search_string ?></p>

<p>下の文章にヒットすると、黄色くハイライトされます。</p>

<p>サンプル文章:</p>

<div>
<?php print $result_string ?>
</div>

</body>
</html>

解説

// 検索される文字列
$target_string = <<< EOM
この本に向いているのはこんな人!<br>
さて、この本はどんな人に向いてそうか、考えてみました。<br><br>

入門書って、読みやすいけど面白いものが作れないからつまらない。<br>
面白いもの作ってみたいけど、たいてい難しい本ばかりで挫折してきた。<br>
楽してプログラミング中級者を名乗りたい<br><br>

といった、勉強したくないけど上達したい!というワガママなあなたにはピッタリです笑<br>
大丈夫、この本を実践し読み終わったころには、自動的に知識がついています。<br>
その後は、中級者向けの本にもすんなり入っていけるようになっているはずです。<br>
是非この本で、プログラミング中級者の仲間入りをしてください!
EOM;

まず、「検索される文字列」を変数に準備します。長いのでヒアドキュメントを使用してます。

 

// 検索する文字列をPOSTで受信する。
$search_string = '';
if(isset($_POST['search_string'])){
	$search_string = htmlspecialchars($_POST['search_string'], ENT_QUOTES, 'UTF-8');
}

「検索する文字列」をPOSTで受信します。

 

// 検索される文字列から検索する文字列を検索し、見つかったらハイライトする。
$result_string = search_highlight($search_string, $target_string);

lib.phpに定義(あとでやります)してある検索処理(search_highlight関数)にかけます。

これは、「検索する文字列」が見つかったら、「検索される文字列」のその部分をハイライトするHTMLタグを追加したものを返し、見つからなければ「検索される文字列」をそのまま返す関数です(のちほど作ります)

 

<form name="search_form" method="POST" action=".">
<input type="text" name="search_string"><input type="submit" value="検索">
</form>

検索窓を作ります。エンターキーまたは、検索ボタンをクリックすると、自分自身のページへ入力された文字列をPOST送信するように、フォームを作ってます。

 

<p>検索キーワード:<?php print $search_string ?></p>

検索したキーワードを表示します。

 

<div>
<?php print $result_string ?>
</div>

ハイライト後のサンプル文章を表示します。

lib.php

ライブラリファイルです。

あいまい検索用の変換処理の関数(search_henkan)と、それを使用して検索し、ハイライトする関数(search_highlight)を定義します。

<?php

// 【PHP】検索文字列をハイライトさせる簡単な方法 ライブラリ

// あいまい検索用の変換処理
function search_henkan($str){

	// 日本語はひらがなに統一(「全角カタカナ」を「全角ひらがな」に変換) 
	$str = mb_convert_kana($str, 'c', 'UTF-8');

	// 英数字は半角に統一(「全角」英数字を「半角」に変換)
	$str = mb_convert_kana($str, 'a', 'UTF-8');

	// 大文字は小文字に統一
	$str = mb_strtolower($str, 'UTF-8');

	return $str;
}

// 検索される文字列から検索する文字列を検索し、ヒットしたらその部分をハイライトして返す。
function search_highlight($search_string, $target_string){

	if(empty($search_string)){ // 検索する文字列が空ならば、検索される文字列をそのまま返す。
		return $target_string;
	}

	// 両者をあいまい検索用の変換にかける。
	$target_string2 = search_henkan($target_string);
	$search_string2 = search_henkan($search_string);

	// 検索する文字列がヒットしたら、ハイライトして返す。

	if(($pos = mb_strpos($target_string2, $search_string2, 0, 'UTF-8')) !== FALSE){ // ヒットしたら
		
		// ヒットしたそれを、検索される文字列(変換前)から取り出す。
		$str = mb_substr($target_string, $pos, mb_strlen($search_string, 'UTF-8'), 'UTF-8');

		// 検索される文字列(変換前)から、検索する文字列をハイライトして、返す。
		return str_replace($str, "<SPAN>{$str}</SPAN>", $target_string);

	}else{ // 見つからなければ、検索される文字列をそのまま返す。
		return $target_string;
	}
}

?>

search_henkan関数の解説

あいまい検索の処理の解説です。仕組みは単純なものです。

「検索する文字列」と、「検索される文字列」について、それぞれあいまい検索用の変換をかけます。

具体的には、以下の3つの変換を行います。

  1. 「全角カタカナ」は「全角ひらがな」に変換
  2. 「全角」英数字は「半角」に変換
  3. 「大文字」は「小文字」に変換

こうした上で、「検索される文字列(変換後)」から、「検索する文字列(変換後)」を検索すれば、半角全角等の違いを無視してヒットさせることができます。

具体的に見ていきましょう。

あいまい検索用の変換にかけずに検索する場合
検索する文字列
(変換前)
検索する文字列
(変換後)
検索される文字列
(変換前)
検索される文字列
(変換後)
検索結果
プログラミング中毒者 衣食住よりプログラミング
~プログラミング中毒者の本音~
衣食住よりプログラミング
プログラミング中毒者の本音~

変換ミスなく検索した場合は、問題なくヒットする。

 

検索する文字列
(変換前)
検索する文字列
(変換後)
検索される文字列
(変換前)
検索される文字列
(変換後)
検索結果
プログラみんぐ中毒者 衣食住よりプログラミング
~プログラミング中毒者の本音~
 衣食住よりプログラミング
~プログラミング中毒者の本音~

検索する文字列に変換ミスがあるので、ヒットしない。

あいまい検索用の変換にかけて検索する場合
検索する文字列
(変換前)
検索する文字列
(変換後)
検索される文字列
(変換前)
検索される文字列
(変換後)
検索結果
プログラみんぐ中毒者 ぷろぐらみんぐ中毒者 衣食住よりプログラミング
~プログラミング中毒者の本音~
衣食住よりぷろぐらみんぐ
~ぷろぐらみんぐ中毒者の本音~
衣食住よりプログラミング
プログラミング中毒者の本音~

検索する文字列に変換ミスがあるが、検索用の変換処理をかけているため問題なくヒットする。

 

// あいまい検索用の変換処理
function search_henkan($str){

	// 日本語はひらがなに統一(「全角カタカナ」を「全角ひらがな」に変換) 
	$str = mb_convert_kana($str, 'c', 'UTF-8');

	// 英数字は半角に統一(「全角」英数字を「半角」に変換)
	$str = mb_convert_kana($str, 'a', 'UTF-8');

	// 大文字は小文字に統一
	$str = mb_strtolower($str, 'UTF-8');

	return $str;
}

これが、今説明した、あいまい検索用の変換処理のコードです。

だいたいイメージは沸きましたでしょうか。

search_highlight関数の解説

それでは次に、search_highlight関数の解説です。

// 検索される文字列から検索する文字列を検索し、ヒットしたらその部分をハイライトして返す。
function search_highlight($search_string, $target_string){

	if(empty($search_string)){ // 検索する文字列が空ならば、検索される文字列をそのまま返す。
		return $target_string;
	}

	// 両者をあいまい検索用の変換にかける。
	$target_string2 = search_henkan($target_string);
	$search_string2 = search_henkan($search_string);

	// 検索する文字列がヒットしたら、ハイライトして返す。

	if(($pos = mb_strpos($target_string2, $search_string2, 0, 'UTF-8')) !== FALSE){ // ヒットしたら
		
		// ヒットしたそれを、検索される文字列(変換前)から取り出す。
		$str = mb_substr($target_string, $pos, mb_strlen($search_string, 'UTF-8'), 'UTF-8');

		// 検索される文字列(変換前)から、検索する文字列をハイライトして、返す。
		return str_replace($str, "<SPAN>{$str}</SPAN>", $target_string);

	}else{ // 見つからなければ、検索される文字列をそのまま返す。
		return $target_string;
	}
}

検索する文字列が見つかったら、検索される文字列のその部分をハイライトするHTMLタグを追加したものを返し、見つからなければ検索される文字列をそのまま返す関数です。

 

if(($pos = mb_strpos($target_string2, $search_string2, 0, 'UTF-8')) !== FALSE){ // ヒットしたら

まず、mb_strpos関数を使って、「検索される文字列(変換後)」から「検索する文字列(変換後)」を探し、見つかるかを判定します。

この関数は、「文字列の中に指定した文字列が最初に現れる位置を見つける」関数です。

公式ドキュメントをチェック

見つかるとFALSE以外が返されるので、FALSE以外が帰ってきたらヒットしたと判定しています。

ヒットすると$posに、最初にヒットした位置が格納されます。

 

// ヒットしたそれを、検索される文字列(変換前)から取り出す。
$str = mb_substr($target_string, $pos, mb_strlen($search_string, 'UTF-8'), 'UTF-8');

検索してヒットしたことがわかったら、「検索される文字列(変換前)」のヒットした箇所をハイライトしたいので、「検索される文字列(変換前)」について、$pos~「検索する文字列」の文字数分だけ取り出します。

ここで取りだしたものが、のちにハイライトするべき文字列となります。

mb_substr関数は、文字列の一部を切り出す関数です。⇒ 公式ドキュメントをチェック

mb_strlen関数は、文字列が何文字かを取得する関数です。⇒ 公式ドキュメントをチェック

 

// 検索される文字列(変換前)から、検索する文字列をハイライトして、返す。
return str_replace($str, "<SPAN>{$str}</SPAN>", $target_string);

「検索される文字列(変換前)」に対して、ハイライトするべき文字列を、ハイライトタグ付きのものに置換し、それを返却すれば完了です。

実行結果

それでは実行してみましょう。

まずは初期状態の画面です。

検索キーワードの入力ボックスに、適当な文字列を入力して、エンターを押してみます。

 

ひらがなとカタカナを間違わずに、検索してみました。見事ヒットして、ハイライトされていますね。

 

今度は、わざとひらがなとカタカナをあべこべにして検索してみました。しかしちゃんとヒットして、ハイライトされています。

これが、あいまい検索のなせる業です。

最後に

今回は簡略化と、検索機能がメインの解説なのでデータベースは使ってません。

検索される対象の文章をデータベースから引っ張ってくることができると、
かなり実用的になるかと思います。

是非試してみてください。

それでは、ありがとうございました。

コメント