質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

3402閲覧

1つのカラムから複数検索

earnest_gay

総合スコア615

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/08/30 03:26

編集2016/08/30 03:54

様々な検索方法を実装したことがなかったので練習がてら色々試しています。

イメージ説明

建物種別のカラムには3種類の値が入っていて、今そこを検索するためのSQK文を書いている最中です。

ラジオボックスを複数選択すると何も表示されません。
1つだけならちゃんとぞれぞれが表示されます。

ソースは下記になりますが、どう改良したらよろしいでしょうか?

$limit = filter_input(INPUT_GET,"limit",FILTER_VALIDATE_INT,["options"=>["default"=>10]]); $sql = sprintf(" SELECT a.`id`, a.`title`, a.`area`, a.`buildingtype`, a.`floorplan`, a.`rento`, a.`deposit`, a.`keymoney`, a.`body`, a.`created`, a.`modified`, c.`companyName` FROM articles a INNER JOIN users u ON a.`user_id` = u.`id` INNER JOIN companys c ON u.`company_id`= c.`id` WHERE title LIKE ? AND ( buildingtype LIKE ? ) AND ( buildingtype LIKE ? ) AND ( buildingtype LIKE ? ) LIMIT %s",$limit ); $search = '%'.filter_input(INPUT_GET,"searchs").'%'; $mansion = '%'.filter_input(INPUT_GET,"mansion").'%'; $apartment = '%'.filter_input(INPUT_GET,"apartment").'%'; $residentialHome = '%'.filter_input(INPUT_GET,"residentialHome").'%'; $bodys = $pdo->prepare($sql); $bodys -> execute([ $search, $mansion, $apartment, $residentialHome ]);

追記

<?php $dsn = 'mysql:dbname=test;host=localhost;charset=utf8'; $user = 'root'; $password = ''; $option = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); $pdo = new PDO($dsn, $user, $password, $option); $sql = "SELECT MIN(rento) as rento FROM articles"; $minRentos = $pdo->query($sql); $minRento=$minRentos->fetch(); $sql = "SELECT MAX(rento) as rento FROM articles"; $maxRentos = $pdo->query($sql); $maxRento=$maxRentos->fetch(); $limit = filter_input(INPUT_GET,"limit",FILTER_VALIDATE_INT,["options"=>["default"=>10]]); $sql = sprintf(" SELECT a.`id`, a.`title`, a.`area`, a.`buildingtype`, a.`floorplan`, a.`rento`, a.`deposit`, a.`keymoney`, a.`body`, a.`created`, a.`modified`, c.`companyName` FROM articles a INNER JOIN users u ON a.`user_id` = u.`id` INNER JOIN companys c ON u.`company_id`= c.`id` WHERE title LIKE ? AND (( buildingtype LIKE ? ) or ( buildingtype LIKE ? ) or ( buildingtype LIKE ? )) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) AND( floorplan LIKE ? ) LIMIT %s",$limit ); $search = '%'.filter_input(INPUT_GET,"searchs").'%'; $mansion = '%'.filter_input(INPUT_GET,"mansion").'%'; $apartment = '%'.filter_input(INPUT_GET,"apartment").'%'; $residentialHome = '%'.filter_input(INPUT_GET,"residentialHome").'%'; $madori1 = '%'.filter_input(INPUT_GET,"1R").'%'; $madori2 = '%'.filter_input(INPUT_GET,"1K").'%'; $madori3 = '%'.filter_input(INPUT_GET,"1DK").'%'; $madori4 = '%'.filter_input(INPUT_GET,"1LDK").'%'; $madori5 = '%'.filter_input(INPUT_GET,"2K").'%'; $madori6 = '%'.filter_input(INPUT_GET,"2DK").'%'; $madori7 = '%'.filter_input(INPUT_GET,"2LDK").'%'; $madori8 = '%'.filter_input(INPUT_GET,"3K").'%'; $madori9 = '%'.filter_input(INPUT_GET,"3DK").'%'; $madori10 = '%'.filter_input(INPUT_GET,"3LDK").'%'; $madori11 = '%'.filter_input(INPUT_GET,"4K").'%'; $madori12 = '%'.filter_input(INPUT_GET,"4DK").'%'; $madori13 = '%'.filter_input(INPUT_GET,"4LDK").'%'; $madori14 = '%'.filter_input(INPUT_GET,"4LDKS").'%'; $madori15 = '%'.filter_input(INPUT_GET,"5LDK~").'%'; $bodys = $pdo->prepare($sql); $bodys -> execute([ $search, $mansion, $apartment, $residentialHome, $madori1, $madori2, $madori3, $madori4, $madori5, $madori6, $madori7, $madori8, $madori9, $madori10, $madori11, $madori12, $madori13, $madori14, $madori15 ]); ?> <!-- ここまで裏の処理 --> <form action="" method="get"> 表示件数 <select name="limit"> <?php for ($i= 5; $i <=50;$i=$i+5){ $selected = $i == 10 ? 'selected': ''; echo '<option value="'. $i .'"'. $selected .'> '. $i .'件づつ</option>'; } ?> </select> <br /> <br /> フリーワード <input type="text" name="searchs"> <br /> <br /> 家賃 <select name="limitMin"> <?php echo '<option value="'.sprintf('%0.1f', 0) .'">下限なし</option><br />'; $startPrice = round($minRento['rento'],-3)/10000; $shredded = 0.5; for ($startPrice; $startPrice <= (round($maxRento['rento'],-3)/10000); $startPrice = $startPrice + $shredded) { echo '<option value="'.sprintf('%0.1f', $startPrice) .'">'.$startPrice .'万円以上</option><br />'; } ?> </select> ~ <select name="limitMax"> <?php $startPrice = round($minRento['rento'],-3)/10000; $shredded = 0.5; for ($startPrice + $swing; $startPrice <= (round($maxRento['rento'],-3)/10000); $startPrice = $startPrice + $shredded) { echo '<option value="'.sprintf('%0.1f', $startPrice) .'">'.$startPrice .'万円以上</option><br />'; } echo '<option value="'.sprintf('%0.1f', 0) .'" selected>上限なし</option><br />'; ?> </select> <br /> <br /> 建物種別 <input type="checkbox" name="mansion" value="マンション">マンション <input type="checkbox" name="apartment" value="アパート">アパート <input type="checkbox" name="residentialHome" value="一戸建て">一戸建て・その他 <br /> <br /> 間取 <?php $madoris = array( '1R', '1K', '1DK', '1LDK', '2K', '2DK', '2LDK', '3K', '3DK', '3LDK', '4K', '4DK', '4LDK', '4LDKS', '5LDK~', ); ?> <?php foreach($madoris as $madori ){ echo '<input type="checkbox" name="' . $madori . '" value="' . $madori . '">' . $madori . ''; } ?> <br /> <br /> <input type="submit" name="submit" value="選択した条件で検索する"> </form> <table border="" width="100%"> <thead> <tr> <th>NO</th> <th>タイトル</th> <th>概要</th> <th>間取</th> <th>建物種別</th> <th>賃料</th> <th>敷金/礼金</th> <th>管理会社</th> <th>公開日</th> </tr> </thead> <tbody> <?php foreach($bodys as $body){ ?> <tr> <td><?php echo $body['id']; ?></td> <td><?php echo $body['title'] ?></td> <td><?php echo $body['body'] ?></td> <td><?php echo $body['floorplan'] ?></td> <td><?php echo $body['buildingtype'] ?></td> <td><?php echo number_format($body['rento']) ?></td> <td><?php echo sprintf('%.1f', ($body['deposit'] / $body['rento']))."/".sprintf('%0.1f', ($body['keymoney'] / $body['rento'])) ?></td> <td><?php echo $body['companyName'] ?></td> <td><?php echo date('Y年m月d日', strtotime($body['created'])); ?></td> </tr> <?php } ?> </tbody> </table>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

ラジオボックス

チェックボックスのこと?
建物種別や間取は複数選択可能でOR検索が必要です
またデータがないときはAND検索しないようにしてください
家賃に関しては下限なしを0、上限なしを1000万とか適当な数字を渡せば
BETWEENで処理ができます

いずれにしてもどういうnameで値を渡しているか提示したほうが良いと思います

追記

なるほど、だいぶわかってきました。
まずbuildingtypeとfloorplanをvarcharで持っていますか?
それは効率がわるいので正規化してください
データはintで持つといいでしょう

shubetuテーブルを用意して
shubetu_id,shubetu_name
1,マンション
2,アパート
3,一戸建て・その他
のようにします。

検索方法は以下簡単なサンプルつけときます

HTML

1<form> 2<input type="checkbox" name="shubetu[]" value="1">マンション 3<input type="checkbox" name="shubetu[]" value="2">アパート 4<input type="checkbox" name="shubetu[]" value="3">一戸建て・その他 5<input type="submit" value="search"> 6</form>

PHP

1$shubetu= filter_input(INPUT_GET,"shubetu",FILTER_VALIDATE_INT , FILTER_REQUIRE_ARRAY)?:array(); 2 3$data=[]; 4$sql="SELECT ・・・ WHERE 1"; 5if(count($shubetu)>0){ 6 $sql.=" AND buildingtype IN(".implode(",",array_fill(1,count($shubetu),"?")).")"; 7 $data=array_merge($data,$shubetu); 8} 9print $sql."<br>"; 10print_r($data); 11//実際にはPDOでexecute($data)する

#このまま検証して

このままのソースで動作を検証してください

PHP

1<?php 2$shubetu= filter_input(INPUT_GET,"shubetu",FILTER_VALIDATE_INT , FILTER_REQUIRE_ARRAY)?:array(); 3 4$data=[]; 5$sql="SELECT * FROM articles WHERE 1"; 6 7if(count($shubetu)>0){ 8$sql.=" AND buildingtype IN(".implode(",",array_fill(1,count($shubetu),"?")).")"; 9$data=array_merge($data,$shubetu); 10} 11print $sql."<br>"; 12print_r($data); 13?> 14<form mothod="get"> 15<input type="checkbox" name="shubetu[]" value="1">マンション 16<input type="checkbox" name="shubetu[]" value="2">アパート 17<input type="checkbox" name="shubetu[]" value="3">一戸建て・その他 18<input type="submit" value="search"> 19</form>

最初はWHERE句に「WHERE 1」が入っている=すべて表示
どれかにチェックを入れて送ると
buildingtypeにIN検索が表示されて絞込をします

投稿2016/08/30 03:51

編集2016/08/30 06:48
yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/08/30 03:57

回答ありがとうございます。 そうです、チェックボックスのことです。 1つのカラムから複数の該当するものを検索対象にしたいのです。 and (( buildingtype LIKE ? ) or ( buildingtype LIKE ? ) or ( buildingtype LIKE ? )) に変更して、アパートと一戸建てにチェックを入れて検索するとなぜかマンションもでてくるようになりました。 どうすれば選択した条件通りの表示ができるようになりますでしょうか... 全部で申し訳ないですが、追記でソース載せております。
yambejp

2016/08/30 04:25

SQLの基本をおさえられてないのかもしれませんね 簡単なサンプル上げておきましたので、これでテストすると理解ができるかも
yambejp

2016/08/30 04:35

他の方の回答をみて気がつきましたがbuildingtypeって普通考えたら 排他的に1つですよね?複数は常識的にありえないのですが もしアパートでありながらマンションな物件というものを想定しているのであれば buildingtypeではなくカラムを分けたほうがよいかもしれません
earnest_gay

2016/08/30 04:42

varcharですが、、、 別テーブルを用意しないとマンションとアパートのレコードを表示できないのでしょうか??? 今回テストで試していることなので目的はテーブルの正規化ではなく、 チェックボックスで選択したものが表示されるかどうかなのです... 例えば、phoneテーブルのcarrierカラムがあったとして、carrierカラムには ・DOCOMO ・AU ・SoftBank の3種類しか入ってないとします。 DOCOMO AU SoftBank DOCOMO AU DOCOMO AU SoftBank SoftBank DOCOMO AU SoftBank と12レコード入っていたとします。(説明のためカラムはcarrierカラム1つだけで話します) ブラウザには ・DOCOMO ・AU ・SoftBank と3つのチェックボックスがあります。 このうち ・DOCOMO ・AU の2つだけをチェックして検索をかけました。 その際にこの2つを取得できるようなSQL文はどうなっているのでしょうかという質問なのですが...
earnest_gay

2016/08/30 04:48

年齢というカラムがあるとして 20歳 30歳 40歳 と格納されているのと同じ考え方です。 建物種別というカラムに対して マンション アパート 一戸建て 性格や入居者というカラムがあったら、別テーブル作るように 1つのレコードが複数の内容を持つ場合はテーブル分けますが、、、
yambejp

2016/08/30 04:50

ごめんなさい、言い方悪いですが「順番が逆です」 SQLは正規化ありきの仕組みなので、このケースでデータを正規化していないものを 検索するのは実務に耐えるものになりません。 ちなみに私のサンプル試しましたか? 検索方法は直接文字がはいっていても、正規化して数値がはいっていても同じです。
earnest_gay

2016/08/30 05:06

サンプルなのですが、なにがどうなっているのかがわかっていないので、既存のコードのどこにどう設置していいのか分からずエラーになってしまいます。。。
yambejp

2016/08/30 05:08

説明がわるかったかもしれませんが、ご提示のソースに直接組み込むものではありません。 単体で実行してみてください
earnest_gay

2016/08/30 05:18

これで実行していんですが、なにをどうすればいいんでしょうか? ブラウザにはSQL文が表示されているだけです... <?php $shubetu= filter_input(INPUT_GET,"shubetu",FILTER_VALIDATE_INT , FILTER_REQUIRE_ARRAY)?:array(); $data=[]; $sql=" SELECT a.`id`, a.`title`, a.`area`, a.`buildingtype`, a.`floorplan`, a.`rento`, a.`deposit`, a.`keymoney`, a.`body`, a.`created`, a.`modified`, c.`companyName` FROM articles a INNER JOIN users u ON a.`user_id` = u.`id` INNER JOIN companys c ON u.`company_id`= c.`id` WHERE title LIKE ? AND ( ( buildingtype LIKE ? ) OR( buildingtype LIKE ? ) OR ( buildingtype LIKE ? ) ) "; if(count($shubetu)>0){ $sql.=" AND buildingtype IN(".implode(",",array_fill(1,count($shubetu),"?")).")"; $data=array_merge($data,$shubetu); } print $sql."<br>"; print_r($data); //実際にはPDOでexecute($data)する ?> <form> <input type="checkbox" name="shubetu[]" value="1">マンション <input type="checkbox" name="shubetu[]" value="2">アパート <input type="checkbox" name="shubetu[]" value="3">一戸建て・その他 <input type="submit" value="search"> </form>
nezume

2016/08/30 05:46

_ノ乙(、ン、)_
guest

0

buildingtypeの設定の仕方が書いていないので何とも言えませんが

AND ( buildingtype LIKE ? )
AND ( buildingtype LIKE ? )
AND ( buildingtype LIKE ? )

and (( buildingtype LIKE ? ) or ( buildingtype LIKE ? ) or ( buildingtype LIKE ? ))

にしなければだめだと思いますよ。

ただ、記述してあるコードに必要な情報が書かれていないので、厳密に動かすにはクエリに渡す前にbuildingtypeの状態によってクエリを変更できるようにしておかないとだめですけどね。

投稿2016/08/30 03:47

編集2016/08/30 03:56
to.chan.genkida

総合スコア69

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/08/30 03:54

ありがとうございます。 変更後、アパートと一戸建てにチェックを入れて検索するとなぜかマンションもでてくるようになりました。。。
to.chan.genkida

2016/08/30 04:00

まずはSQLの基礎を見直した方が良いと思います。
guest

0

テーブルの正規化しましょうよ…というのはさておき :p

建物種別のカラムには3種類の値が入っていて

と言うのは buildingtype カラムの中に
"アパート 一戸建て マンション"と入っている(ケースがある)のでしょうか?
それとも buildingtype カラムには
"アパート"か"一戸建て"か"マンション"の何れか一つのみが入っているのでしょうか。
(まぁ、後者ですよね)

最初のポストにあった SQL に"アパート"と"一戸建て"をチェックした状態で検索させると
下記の様な SQL が実行されるはずですが、先頭に何もかもマッチさせる条件がありますので

buildingtype like '%%' or buildingtype like '%アパート%' or buildingtype like '%一戸建て%'

to.chan.genkida さんの提示された修正方法でマンションも出てくるようになって当然です。
(断っておきますが、演算子を and から or に変えるのは完全な正解です)
選択項目の数が可変なので検索条件部分をどうにかすることを考えないといけません。
このあたりも to.chan.genkida さんがおっしゃっている通りです。

投稿2016/08/30 04:29

編集2016/08/30 04:55
nezume

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

earnest_gay

2016/08/30 04:52

後者がよくわかりませんが、 buildingtype カラムには マンション アパート 一戸建て この3つしかないです。
nezume

2016/08/30 04:57

yambejp さんがズバリな正解を書かれています。 それは試されましたか?
earnest_gay

2016/08/30 05:28

buildingtype like '%%' この部分をヒントにさせていただき、 三項演算子を使って %%表示の切り替えをしたらうまく動作しました。 そもそもget時のname値がbuildingtypeカラムに格納されているものと完全一致のため、あいまい検索する必要がなかったので、単純に取り外しても動作しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問