・複数のキーワードで検索できるようにする
・AND OR 条件を切り替えて検索できるようにする
キーワードはスペースで区切ることにします。スペースは全角でも半角でもかまいません。AND OR の選択にはラジオボタンを使います。
実は複合語検索できるようにするには、いろんな条件を想定しなければならないため複雑ですが、今回は最も基本的な機能に絞って説明します。基本をつかめばあとは少しずつ改良できます。
【1】sample107 フォルダをコピーして sample108 フォルダを作成します。

【2】今回は以下のようなファイルの構成になります。

・select.php、search.phpは変更があります。
・他のファイルは前回の sample107 と同じものなので、ソースコードは省略します。
*「\」はWindowsではエンマークのことです。
保存先 C:\phpdev\www\test\sample108
ファイル名 select.php
<?php
//ファイルを読み込み
require_once("SampleDB050.php");
// クエリを送信する
$sql = "SELECT * FROM T01Prefecture ORDER BY PREF_CD";
$result = executeQuery($sql);
//結果セットの行数を取得する
$rows = mysql_num_rows($result);
//表示するデータを作成
if($rows){
while($row = mysql_fetch_array($result)) {
$tempHtml .= "<tr>";
$tempHtml .= "<td>".$row["PREF_CD"]."</td><td>".$row["PREF_NAME"]."</td>";
$tempHtml .= "<td><a href=\"update.php?cd=".$row["PREF_CD"]."\" target=\"_self\">更新</a></td>";
$tempHtml .= "<td><a href=\"delete.php?cd=".$row["PREF_CD"]."\" target=\"_self\">削除</a></td>";
$tempHtml .= "</tr>\n";
}
$msg = $rows."件のデータがあります。";
}else{
$msg = "データがありません。";
}
//結果保持用メモリを開放する
mysql_free_result($result);
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=SHIFT-JIS">
<title>全件表示</title>
<script type="text/javascript" src="select.js"></script>
</head>
<body>
<h3>全件表示</h3>
<form name="form2" action="search.php" method="post">
<input type="text" name="keyword" size="25">
<input type="submit" name="search" value="検索"><br />
<input type="radio" checked name="searchSelect" value="AND">AND
<input type="radio" name="searchSelect" value="OR">OR
</form>
<?= $msg ?>
<table width = "300" border = "1">
<tr bgcolor="##ccffcc"><td>PREF_CD</td><td>PREF_NAME</td><td colspan="2">EDIT</td></tr>
<?= $tempHtml ?>
<form name="form1" action="insert.php" method="post">
<tr>
<td><input type="text" name="cd" id="cd"></td>
<td><input type="text" name="name"></td>
<td colspan="2">
<input type="submit" name="insert" value="追加"><input type="reset" value="リセット">
</td>
</tr>
</form>
</table>
</body>
</html>
保存先 C:\phpdev\www\test\sample108
ファイル名 search.php
<?php
//ファイルを読み込み
require_once("SampleDB050.php");
//データを取得する
$searchSelect = $_POST['searchSelect'];
$keyword = $_POST['keyword'];
$keyword = str_replace(" ", " ", $keyword);
$keyword = trim($keyword);
//検索キーワード未入力時
if(empty($keyword)){
print "<html>";
print "<head><title>未入力</title></head>";
print "<body>";
print "検索キーワードが入力されていません。";
print "<p><a href=\"select.php\" target=\"_self\">全件表示へ</a><p>";
print "</body>";
print "</html>";
exit;
}
//抽出条件を組み立てる
$array = explode(" ", $keyword);
$cnt = count($array);
$where = "WHERE ";
for($i=0; $i < $cnt; $i++){
$where.= "PREF_NAME LIKE '%".$array[$i]."%'";
if($i < $cnt-1){
$where .=" ".$searchSelect." ";
}
}
// クエリを送信する
$sql = "SELECT * FROM T01Prefecture ".$where;
$sql .= " ORDER BY PREF_CD";
$result = executeQuery($sql);
print $sql;
//結果セットの行数を取得する
$rows = mysql_num_rows($result);
//表示するデータを作成
if($rows){
while($row = mysql_fetch_array($result)) {
$tempHtml .= "<tr>";
$tempHtml .= "<td>".$row["PREF_CD"]."</td><td>".$row["PREF_NAME"]."</td>";
$tempHtml .= "<td><a href=\"update.php?cd=".$row["PREF_CD"]."\" target=\"_self\">更新</a></td>";
$tempHtml .= "<td><a href=\"delete.php?cd=".$row["PREF_CD"]."\" target=\"_self\">削除</a></td>";
$tempHtml .= "</tr>\n";
}
$msg = $rows."件のデータがあります。";
}else{
$msg = "データがありません。";
}
//結果保持用メモリを開放する
mysql_free_result($result);
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=SHIFT-JIS">
<title>検索結果</title>
<script type="text/javascript" src="select.js"></script>
</head>
<body>
<h3>検索結果</h3>
<form name="form2" action="search.php" method="post">
<input type="text" name="keyword" size="25" value="<?= $keyword ?>">
<input type="submit" name="search" value="検索"><br />
<input type="radio" checked name="searchSelect" value="AND">AND
<input type="radio" <?= ($searchSelect == "OR")? "checked" : "" ?> name="searchSelect" value="OR">OR
</form>
<?= $msg ?>
<table width = "300" border = "1">
<tr bgcolor="##ccffcc"><td>PREF_CD</td><td>PREF_NAME</td><td colspan="2">EDIT</td></tr>
<?= $tempHtml ?>
<form name="form1" action="insert.php" method="post">
<tr>
<td><input type="text" name="cd" id="cd"></td>
<td><input type="text" name="name"></td>
<td colspan="2">
<input type="submit" name="insert" value="追加"><input type="reset" value="リセット">
</td>
</tr>
</form>
</table>
<p><a href="select.php" target="_self">全件表示へ</a><p>
</body>
</html>
【3】C:\phpdev にある 2K-NT-XP-phpdev_start.bat をダブルクリックして、phpdev を起動します。

準備ができたら作成したPHPプログラムを実行してみましょう。
【4】ブラウザのアドレスに http://localhost/test/sample108/select.php と入力し、実行します。
【5】全件表示(select.php)の画面が表示されました。検索用のテキストボックスの下に、ANDとORのラジオボタンが表示されています。

【6】テキストボックスに「山」と入力し、「AND」を選択して「検索」ボタンをクリックします。

【7】検索結果(search.php)の画面が表示されました。「山」を含む都道府県の一覧が表示されています。

・確認のためプログラムで組み立てたSQL文を表示しています。
・検索キーワードが1つなので、普通のあいまい検索になっています。
・テキストボックスには select.php で入力したキーワードが表示されています。
【8】次はキーワードをスペースで区切り「山 岡」と入力し、「AND」を選択して「検索」ボタンをクリックします。

*スペースは半角でも全角でもかまいません。ただしスペースを2つ以上続けないでください。
【9】検索結果(search.php)の画面が表示されました。「山」かつ「 岡」を含む都道府県の一覧が表示されています。

SQL文を見ると抽出条件が AND でつながっています。AND は両方のキーワードが含まれていなければならないので、岡山県しかありません。
【10】次はキーワードをスペースで区切り「山 岡」と入力し、「OR」を選択して「検索」ボタンをクリックします。

【11】検索結果(search.php)の画面が表示されました。「山」または「岡」を含む都道府県の一覧が表示されています。

SQL文を見ると抽出条件が OR でつながっています。ORはどちらか一つのキーワードが含まれていればよいので、表示件数は多くなります。
【12】次はキーワードをスペースで区切り「児 島 鹿」と入力し、「OR」を選択して「検索」ボタンをクリックします。

【13】検索結果(search.php)の画面が表示されました。「児」または「島」または「鹿」を含む都道府県の一覧が表示されています。

SQL文の OR が2つになり、3語以上のキーワードにも対応していることが確認できました。
都道府県名は多くても4文字なので、AND検索で多くのキーワードを使うことは無いと思いますが、OR検索では役立ちます。
【解説】
■select.php
(1)検索用のテキストボックスのサイズを少し大きくし、ANDとORのラジオボタンを追加しました。デフォルトでは AND が選択(checked)されるようにしています。
<form name="form2" action="search.php" method="post">
<input type="text" name="keyword" size="25">
<input type="submit" name="search" value="検索"><br />
<input type="radio" checked name="searchSelect" value="AND">AND
<input type="radio" name="searchSelect" value="OR">OR
</form>
■search.php
(1)ラジオボタンのデータを取得する部分です。AND か OR の文字列が代入されます。
$searchSelect = $_POST['searchSelect'];
(2)キーワードのデータを取得する部分です。
$keyword = $_POST['keyword'];
$keyword = str_replace(" ", " ", $keyword);
$keyword = trim($keyword);
キーワードに全角のスペースが含まれている場合は、str_replace()関数で半角スペースに置換して、trim()関数で文字列の前後の空白を除いています。
これはキーワードの前後にスペースが入っていた場合の対策です。またキーワードを半角スペースで区切る準備も兼ねています。
例えば文字列が「 A BC DEF 」の場合、trim()関数で除けるのは「Aの前」と「Fの後」の空白だけです。文字列内の空白は除けません。
(3)キーワードが未入力の場合はメッセージを表示して、「exit;」で現在のスクリプトを終了しています。exitより下に書かれているものは表示されません。htmlやbodyのタグも表示されないので、最低限のHTMLタグは print で出力しています。
if(empty($keyword)){
print "<html>";
print "<head><title>未入力</title></head>";
print "<body>";
print "検索キーワードが入力されていません。";
print "<p><a href=\"select.php\" target=\"_self\">全件表示へ</a><p>";
print "</body>";
print "</html>";
exit;
}
(4)複数の検索キーワードにも対応できるように、抽出条件を組み立てる部分を変更しました。
検索キーワードを「半角スペース」で区切り、配列に格納する
$array = explode(" ", $keyword);
キーワード数(配列の要素数)を数える
$cnt = count($array);
変数に抽出条件の文字列を代入する
$where = "WHERE ";
for文でキーワード数の回数だけ繰り返しています。if文で最後のキーワードになるまでは AND か OR でつなぎます。
for($i=0; $i < $cnt; $i++){
$where.= "PREF_NAME LIKE '%".$array[$i]."%'";
if($i < $cnt-1){
$where .=" ".$searchSelect." ";
}
}
(5)前の画面でテキストボックスに入力した値を、デフォルトで表示しています。
<input type="text" name="keyword" size="25" value="<?= $keyword ?>">
(6)前の画面でORラジオボタンが選択されていた場合は、選択(checked)します。
<input type="radio" <?= ($searchSelect == "OR")? "checked" : "" ?> name="searchSelect" value="OR">OR
デフォルトでは AND が選択(checked)されるようになっているので、ORの場合だけ切り替えればよいわけです。
【ワンポイント】
検索ボックスに入力されたキーワードを、半角スペースで区切って取り出しているので、文字列内に半角スペースが2つ以上続くと空白がキーワードとなります。そうするとSQL文で「PREF_NAME LIKE '%%'」となるため、全てのレコードが抽出されてしまいます。
これを防ぐには正規表現を使い、1つ目のスペースだけ残し、2つ以上のスペースを除くようにプログラムすると解決できます。