こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

PHPでMySQLを使った検索のプログラム

「たったコレだけでPHPプログラミングが理解できる本」を参考にPHPでプログラムを書いていまして、
ビジネスホテルの検索機能をチェックボックス機能を余分につけて検索できないか試したのですが、
チェックボックスにチェックを入れると全く検索できず他のテキストボックスに入力するだけなら検索できます。
なんとかチェックボックスを有効にできないかいろいろなサイトを調べたり本を読んだりしましたが解決策が見つかりません。

いろいろな機能に対応できるようなプログラムを組みたいと思ったのでかなりの初心者で大変恐縮ですが、どなたかご教授お願いできないかと思っております。

あと参考になるサイトがございましたら、教えていただきたいと思っております。
何卒よろしくお願い致します。




前半省略



<form name="search_form" action="" method="post" >
<input type="hidden" name="cmd" value="search" />
<table>

<tr>
<th>物件種別</th>

<td>
<input type="checkbox" name="kodawari_key[]" value="温泉" <?php if( $_REQUEST["kodawari_key"] == "温泉" ){ print( 'checked' ); } ?>/>
温泉
<input type="checkbox" name="kodawari_key[]" value="ランチ" <?php if( $_REQUEST["kodawari_key"] == "ランチ" ){ print( 'checked' ); } ?>/>
ランチ<br />
<input type="checkbox" name="kodawari_key[]" value="ディナー" <?php if( $_REQUEST["kodawari_key"] == "ディナー" ){ print( 'checked' ); } ?>/>
ディナー</td>

</tr>
<tr>
<th>価格帯</th>
<td>
<input type="text" name="price_min" value="<?php print( htmlspecialchars( $_REQUEST["price_min"] ,ENT_QUOTES ) ) ?>" size="8"> ~
<input type="text" name="price_max" value="<?php print( htmlspecialchars( $_REQUEST["price_max"] ,ENT_QUOTES ) ) ?>" size="8"><br />
</td>
</tr>
<tr>
<th>住所</th>
<td><input type="text" name="address" value="<?php print( htmlspecialchars( $_REQUEST["address"] ,ENT_QUOTES ) ) ?>" size="20"></td>
</tr>


</table>
<input type="submit" value="検索" class="Btn-gray button">
</form>

<p>&nbsp;</p>




<?php


if( $_REQUEST["cmd"] == "search" ){
$pdo = new PDO("mysql:host=localhost; dbname=hotel_reservation; charset=utf8", "koredake", "koredake123", array( PDO::ATTR_EMULATE_PREPARES => false ) );

$sql = "select * from hotels where 1 = 1 ";
$condition = array();

if( !empty( $_POST["kodawari_key"] )){
$sql = $sql . " and kodawari_key = :kodawari_key";
$condition["kodawari_key"] = $_REQUEST["kodawari_key"];
}

if( !empty( $_REQUEST["price_min"] ) ){
$sql = $sql . " and price >= :price_min ";
$condition[":price_min"] = $_REQUEST["price_min"];
}

if( !empty( $_REQUEST["price_max"] ) ){
$sql = $sql . " and price <= :price_max ";
$condition[":price_max"] = $_REQUEST["price_max"];
}

if( !empty( $_REQUEST["address"] ) ){
$sql = $sql . " and ( pref like :pref or city like :city or address like :address ) ";
$condition[":pref"] = "%{$_REQUEST["address"]}%";
$condition[":city"] = "%{$_REQUEST["address"]}%";
$condition[":address"] = "%{$_REQUEST["address"]}%";
}



$statement = $pdo->prepare( $sql );
$statement->execute( $condition );
$results = $statement->fetchAll();
?>



<table border="1">
<caption>検索結果</caption>
<tr>
<th></th>
<th>ホテル名</th>
<th>宿泊料金</th>
<th>住所</th>
</tr>

<?php
foreach( $results as $result ){
?>
<tr>
<td><img src="hotel/<?php print( htmlspecialchars( $result["id"], ENT_QUOTES )); ?>.png" /></td>
<td><?php print( htmlspecialchars( $result["hotel_name"], ENT_QUOTES )); ?></td>
<td>\<?php print( htmlspecialchars( number_format( $result["price"] ),ENT_QUOTES ) ); ?></td>
<td>
<?php print( htmlspecialchars( $result["pref"], ENT_QUOTES ) ); ?>
<?php print( htmlspecialchars( $result["city"], ENT_QUOTES ) ); ?>
<?php print( htmlspecialchars( $result["address"], ENT_QUOTES ) ); ?>
</td>
</tr>
<?php
}
}
?>
</table>
</div>
</body>
</html>

投稿日時 - 2014-06-15 17:38:15

QNo.8639163

困ってます

質問者が選んだベストアンサー

#3です
PHPへの組み込みについては、今後学習していただくとして
一応SQLのサンプル

//ホテルの基本情報
CREATE TABLE t_hotels(id int not null primary key,name varchar(100) not null,price_min int not null,price_max int not null,address varchar(100) not null);
INSERT INTO t_hotels VALUES(1,'HOTEL A',5000,10000,'栃木県・・・'),
(2,'HOTEL B',5000,12000,'栃木県・・・'),
(3,'HOTEL C',6000,9000,'千葉県・・・'),
(4,'HOTEL D',5000,10000,'千葉県・・・'),
(5,'HOTEL E',4000,5000,'埼玉県・・・'),
(6,'HOTEL F',15000,30000,'東京都・・・'),
(7,'HOTEL G',12000,40000,'神奈川県・・・');

//こだわり情報
CREATE TABLE t_kodawari_key(id int not null primary key,name varchar(20));
INSERT INTO t_kodawari_key VALUES(1,'温泉'),(2,'ランチ'),(3,' ディナー');

//ホテルごとのこだわり
CREATE TABLE t_hotel_kodawari(hid int not null,kid int not null,unique key(hid,kid));
INSERT INTO t_hotel_kodawari VALUES(1,1),(1,2),(1,3),(2,1),(3,2),(3,3),(4,3);

//温泉かランチにこだわりがあるところ
SELECT hid,t3.name,t3.price_min,t3.price_max,GROUP_CONCAT(t2.name) as kodawari,t3.address
FROM t_hotel_kodawari as t1
INNER JOIN t_kodawari_key as t2 ON t1.kid=t2.id AND t1.kid IN (1,2)
INNER JOIN t_hotels as t3 ON t3.id=t1.hid
GROUP BY hid

//温泉かランチかディナーのうち2つ以上にこだわりがあるところ
SELECT hid,t3.name,t3.price_min,t3.price_max,GROUP_CONCAT(t2.name) as kodawari,t3.address
FROM t_hotel_kodawari as t1
INNER JOIN t_kodawari_key as t2 ON t1.kid=t2.id AND t1.kid IN (1,2,3)
INNER JOIN t_hotels as t3 ON t3.id=t1.hid
GROUP BY hid
HAVING count(*)>=2

投稿日時 - 2014-06-16 16:51:01

お礼

yambejp様、追記していただき誠にありがとうございます。
kodawari_key用のテーブルを1つ作成するだけで良かったと思ったのですが、そうでもなかったのですね。
まさかのcheckboxがこんなに難しいものだとは思いもよりませんでした。
このテーブルに対応したPHPを書くことは難しそうですが、なんとか頑張ってみたいと思います。

とは言ったものの正直このもやもや感なんとかしたいものです。
追記していただき、本当に感謝いたします!

投稿日時 - 2014-06-16 20:08:16

ANo.4

このQ&Aは役に立ちましたか?

12人が「このQ&Aが役に立った」と投票しています

-広告-
-広告-

回答(4)

ANo.3

根本的な考え方としてSQLには正規化というルールがあります

今回のkodawari_keyのように情報提供側から選択肢をあたえて選ばせるようなものは
別テーブルをつくって正規化したほうがいいでしょう。

テーブル:t_kodawari_key
id name
1 温泉
2 ランチ
3 ディナー

この場合、htmlの表記は
<input type="checkbox" name="kodawari_key[]" value="1" <?php if( $_REQUEST["kodawari_key"] == "1" ){ print( 'checked' ); } ?>/>
温泉

となります。
hotelsテーブルの、kodawari_keyの持ち方はt_kodawari_keyのidを指定します。

しかしこの持ち方では、各hotelはkodawari_keyを1つしかもてません
hotelごとに複数のkodawari_keyを持つためにはさらに別テーブルt_hotel_kodawari
をつくって、複数指定できるようにします

t_hotel_kodawari
hid kid
1 1
1 2
1 3
2 1
3 2

ホテルのidをhidとしhid=1のホテルは1,2,3のkodawari_keyをもち
hid=2のホテルは1,hid=3のホテルは2のkodawari_keyを持ちます
このあたりが理解できないと、後々データ管理がきびしくなるでしょう

投稿日時 - 2014-06-16 11:36:12

お礼

ご指摘感謝いたします。

展開するということがわかっていなかったので、プログラムをもう少ししっかり読まないといけません。

まさにご指摘されたとおりのことで悩んでおりました。
yambejp様の仰るとおりで、一つのホテルに複数のkodawari_keyがある場合にどのようなプログラムを書けばよいのか初心者の私にはかなり難しいところです。

kodawari_key用のテーブルをもう一つ作ってidをつけて紐付けしてから一つのidに対して値が複数あるものに対しては複数入れるということですね。
あとはプログラムをどう実現するかです。

ありがとうございました。

投稿日時 - 2014-06-16 14:13:08

ANo.2

$_POST["kodawari_key"] を処理している箇所を以下のようにするといいでしょう

■物件種別が and 条件なら
if( !empty( $_POST["kodawari_key"] )){
for($i=0; $i<count($_REQUEST["kodawari_key"]); $i++) {
$tmpKey = "kodawari_key".$i;
$sql .= " and kodawari_key = :".$tmpKey;
$condition[$tmpKey] = $_REQUEST["kodawari_key"][$i];
}
}

■物件種別が or 条件なら
if( !empty( $_POST["kodawari_key"] )){
$sql .= " and ( 1=1 ";
for($i=0; $i<count($_REQUEST["kodawari_key"]); $i++) {
$tmpKey = "kodawari_key".$i;
$sql .= " or kodawari_key = :".$tmpKey;
$condition[$tmpKey] = $_REQUEST["kodawari_key"][$i];
}
$sql .= ")";
}

投稿日時 - 2014-06-15 23:34:00

お礼

追記していただき、感謝します。
まだまだ理解不足なので自分なりに試してみましたがうまくいきませんでした。
ある程度自分で解決するスキルがないとPHPは難しいですね。

投稿日時 - 2014-06-16 13:32:36

ANo.1

$_POST["kodawari_key"] の中身は配列で入っているはずですが、展開せずに渡しているのが問題でしょう。
また、SQLの方が kodawari_key = :kodawari_key となっているので、複数チェックされている場合は正しい検索が出来ませんので kodawari_key in ( :kodawari_key ) といった条件式にする必要があると思います。

投稿日時 - 2014-06-15 18:54:39

補足

t_ohtaさん、お答えいただき誠にありがとうございます。
var_dump($_REQUEST)で 試したところ、["kodawari_key"]=> array(2)とかえってきたので、配列だということは確認できたのですが、素人丸出しの質問で恐縮ですが、「$_POST["kodawari_key"]」を展開するということは具体的にどのように記述すれば良いのでしょうか?
もしお時間がございましたらお答えいただけたらありがたいと思っております。

投稿日時 - 2014-06-15 20:11:30

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-