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

解決済みの質問

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

まだ解決できないので、大変恐縮ですがご教授お願いします。
どうかよろしくお願いいたします。

数人にご教授いただいき、チェックボックスの選択には一つのkid(kodawari_keyの略)に対して2複数の値をもっているホテルを表示させるにはデータベースのtableを複数に分けて紐付けする必要があるとアドバイスをいただき、教えて頂いたとおりtableをホテル用とチェックボックス用とチェックボックスのid用とに分けて、SQL文で紐付けしたつもりだったのですが、チェックボックスをチェックしてから検索ボタンを押すと
Fatal error: Call to a member function execute() on a non-object in C:\xampp\htdocs\koredake\xxxxx\xxxxxxx.php on line 97
のようなエラーが出てしまいます。

このことから紐付けのSQL文が間違っているのではと思うのですが、正解がわかりません。
どなたか教えていただけたらと思っております。

//MySQLの部分 教えていただいた部分で大変恐縮です。

//ホテルの基本情報
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,'栃木県・・・'),

//こだわり情報
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

//温泉かランチかディナーのうち2つ以上にこだわりがあるところ
SELECT hid,t3.name,t3.price_min,t3.price_max,GROUP_CONCAT(t2.name) as kodawari,t3.address


//PHP部分 前半省略

<h1>ビジネスホテルの条件検索</h1>

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

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


<td>
<input type="checkbox" name="kid[]" value="1" <?php if( $_REQUEST["kid"] == "1" ){ print( 'checked' ); } ?>/>
温泉
<input type="checkbox" name="kid[]" value="2" <?php if( $_REQUEST["kid"] == "2" ){ print( 'checked' ); } ?>/>
ランチ<br />
<input type="checkbox" name="kid[]" value="3" <?php if( $_REQUEST["kid"] == "3" ){ print( 'checked' ); } ?>/>
ディナー
<input type="checkbox" name="kid[]" value="4" <?php if( $_REQUEST["kid"] == "4" ){ 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 t_hotels where 1 = 1 ";
$condition = array();


//この部分が特に自信が無いです。
if( !empty( $_POST["kid"] )){
$sql = $sql . " left outer join kid on t_hotels.hid = kid.hid";

}

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 ( address like :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["address"], ENT_QUOTES ) ); ?>

</td>
</tr>
<?php
}
}
?>
</table>
</div>

投稿日時 - 2014-06-17 02:07:07

QNo.8641518

困ってます

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

>>あまり最初から詰め込みすぎずに、徐々に条件を付けていった方がいいですよ

>ということはもっと単純な条件式で大丈夫なのでしょうか?

え~と、そういうことではなく、たくさん条件を最初から書くと
どの条件節でエラーになっているかわかりづらくなるということです。
今回の質問であれば「こだわり」の部分が問題だったのですから
ほかの上限や下限料金、住所などはばっさりコメントアウトしてまえば
エラーの切り分けができるので、どこを直せばいいか絞り込めます。
デバグをするときにはなるべく簡潔な処理まで切り詰めた方がいいということです。
(まぁ複合バグもあるのでケースバイケースですが・・・)

>LEFT OUTER JOINを変更して

ちなみに、こまかく見てないのでなんともいえませんが
今回の例だとLEFT JOINした場合はWHEREやHAVINGの処理をかませないと
絞り込みになっていないかもしれません

>何もcheckboxや他の項目をチェックしなかったら、全てのホテルが表示されてしまします。
>本当はチェックしなかったら、表示されないようにしたいのですが。

通常の絞り込みのロジックはこう

WHERE 1 AND 条件1 AND 条件2 ・・・
AND検索なのですべての条件に当てはまるものが絞り込まれます。
条件が何もない場合なにも表示しないなら
フラグ管理して、条件句に条件を付加していくときにフラグを立てるようにし
フラグが0の際には条件句の最後に「AND 0」を足せばいいでしょう。

$flag=0;
$sql="SELECT * FROM tbl WHERE 1 ";

if(条件1){
$sql.="AND hoge='hogehoge' ";
flag=1;
}
if(条件2){
$sql.="AND fuga BETWEEN 'xxx' AND 'yyy' ";
flag=1;
}
if(条件3){
$sql.="AND piyo LIKE 'zzz%' ";
flag=1;
}

if($flag==0){
$sql.="AND 0 ";
}

投稿日時 - 2014-06-19 15:17:43

補足

checkboxの値で間違いがわかりました。
いろいろプログラム変更していたらフォームをname属性からvalue属性に変えてしまっていて、値の受け渡しができていませんでした。
PHPは何か変な仕様ですね。

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

投稿日時 - 2014-06-20 15:51:47

お礼

親切に教えていただきいつもありがとうございます。

$sql="全体を表す文";で後はandで絞り込むのですね。
大変勉強になります。ある程度の基本があるのですね。

いろいろな全体のSQLの文を考えたのですが、最初の
checkboxのkidが値を拾っていないというか何も受けていないことが
var_dump($sql);
によってわかりました。
checkboxのフォームが悪いのか受け方は変更したのですが、上手くいきません。
やはりデータベースは難しいですね。
誠に恐縮ですが、また機会がありましたらご教授いただけたらと思います。

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

投稿日時 - 2014-06-20 02:19:21

ANo.2

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

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

回答(2)

ANo.1

>$sql = $sql . " left outer join kid on t_hotels.hid = kid.hid";

とありますが・・・
「kid」というテーブルがあるようにみえませんが?

あまり最初から詰め込みすぎずに、徐々に条件を付けていった方がいいですよ

投稿日時 - 2014-06-19 09:54:02

お礼

yambejp様、いつもご指摘感謝いたします。

ということは私はワリと単純なミスで数日間止まっていたんですね。

>あまり最初から詰め込みすぎずに、徐々に条件を付けていった方がいいですよ

ということはもっと単純な条件式で大丈夫なのでしょうか?
本のせいにするわけじゃないですけど書籍など調べると

SELECT * FROM テーブル1 INNER JOIN テーブル2 ON テーブル1.テーブル1のカラム = テーブル2.テーブル2のカラム

だとか場合によっては上記のINNER の部分をLEFT OUTER JOINを変更して条件式あたりを使ってWHEREで絞り込むのだと本に書いてあったので構文が必要だと思っていたのですが勝手な先入観だったのかもしれません。

本だと内部結合、外部結合のなどの構文が最初に出てくるのでそれらを使わないと複数のテーブルを扱えないと思っていたのですが、どうなのでしょう?
yamabejp様のアドバイスを受けたら勘違いな気がしてきました。

LEFT OUTER JOIN のkidをt_hotel_kodawari.idに直したら文法のerrorは直りました。

ただ問題なのは何もcheckboxや他の項目をチェックしなかったら、全てのホテルが表示されてしまします。

本当はチェックしなかったら、表示されないようにしたいのですが。

条件文を単純にしていきたいを思います。

おかげ様で正解に近づいてきていると思います。
ありがとうございます。

投稿日時 - 2014-06-19 13:37:14

あなたにオススメの質問