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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

Q&A

解決済

2回答

964閲覧

【PHPmySQL】チェックボックス・フリーワードでの検索条件の絞り込み方法

otokichi_

総合スコア25

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

PHP

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

0グッド

1クリップ

投稿2017/08/23 10:04

編集2017/08/23 13:52

PHPmySQLでデータベースの検索結果を出力したいです。
接続はPDOで行いました。テーブル(適当)の画像は下に貼っておきます。

下記コードでは、フリーワードで入力した値は出力できる
ようになっています。チェックボックスや、フリーワードで
絞り込み検索する事が難しいです。

やりたい事を下部画像で言うと2つです。
・東京都にチェックを入れたら、所在地が東京都の行を出力する。

・東京都にチェックいれてフリーワードを入力すると、所在地が
東京かつフリーワードが含まれる行を出力する。

色々調べて挫折したため、ご教授いただけると大変助かります。
ご不備等ありましたら遠慮なくご指摘ください。
どうぞよろしくお願いいたします。

php

1<?php 2 3$database = 'mysql:dbname=trainning'; 4$host = 'localhost'; 5$username = 'trainning'; 6$password = 'password'; 7$table_name = 'tablename'; 8 9$options = array( 10 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', 11); 12 13try{ 14 15 $pdo = new PDO($database, $username, $password, $options); 16 $pdo->query('SET NAMES utf8'); 17 print('<br>'); 18 19 if ($pdo == null){ 20 21 print('接続に失敗しました。<br>'); 22 23 } 24 25 $pdo->query('SET NAMES utf8'); 26 27 28}catch (PDOException $e){ 29 print('Error:'.$e->getMessage()); 30 die(); 31} 32 33?> 34 35<html> 36<head> 37<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 38<title>search engine1.1</title> 39 40</head> 41 42<body> 43 44<center><h1>search engine1.1</h1> 45 46<form action="" method="get"> 47 48 <input type="checkbox" name="search1" value="東京都" ><label>東京都</label><br> 49 <input type="checkbox" name="search2" value="大阪府"><label>大阪府</label><br> 50 <input type="checkbox" name="search3" value="愛知県"><label>愛知県</label><br> 51 <input type="checkbox" name="search4" value="福岡県"><label>福岡県</label><br> 52 <input type="checkbox" name="search5" value="海外"><label>海外</label> 53 54 <p><input type="search" name="search6" size="30" maxlength="255"placeholder="Search..."> 55 <input type="submit" value="検索"></p> 56 57</form> 58 59 60</center> 61 62 63<?php 64$search_type_and = false; 65$raw_keyword = $_GET["search"]; 66print("検索したキーワード [ ".$raw_keyword." ]<br>"); 67 68//文字入力があれば実行 69if(null != $raw_keyword){ 70 71 if(isset($_GET["page"]) && preg_match("/^[0-9]+$/", $_GET["page"])){ 72 $page_number = (int)$_GET["page"]; 73 if($page_number <= 0) $page_number = 1; 74 } 75 else{ 76 $page_number = 1; 77 } 78 $page_articles = 10; // 1ページに表示する件数(定数) 79 $offset = ($page_number - 1) * $page_articles; // オフセットを計算 80 81 82 $keywords = explode(" ", trim(str_replace(" ", " ", $raw_keyword))); 83 84 $target_columns = array( 85 86 "番号", 87 "企業名", 88 "ヨミガナ", 89 "上場企業", 90 "所在地", 91 "資本金", 92 "売上高", 93 "業種", 94 "事業内容", 95 "従業員数", 96 "備考欄", 97 "PDFURL" 98 99 ); 100 101 $where = array(); 102 103 104 foreach($target_columns as $index_column => $column){ // カラムのループ 105 $tmp = array(); 106 foreach($keywords as $index_keyword => $keyword){ // キーワードのループ 107 $tmp[] = "{$column} LIKE :keyword{$index_column}_{$index_keyword}"; 108 } 109 110 /* AND検索なら、すべてのキーワードが含まれるデータを対象とする 111 上のループで作ったLIKE文の配列を " AND " で繋げる */ 112 $where[] = join($search_type_and ? " AND " : " OR ", $tmp); 113 } 114 115 $query = "SELECT SQL_CALC_FOUND_ROWS * FROM {$table_name} WHERE " . join(" OR ", $where). 116 " LIMIT {$offset}, {$page_articles}"; 117 118 $stmt = $pdo->prepare($query); 119 120 foreach($target_columns as $index_column => $column){ 121 foreach($keywords as $index_keyword => $keyword){ 122 if(!$stmt->bindValue(":keyword{$index_column}_{$index_keyword}", "%{$keyword}%")) { 123 exit("Failed to bind value: " . $keyword); 124 } 125 } 126 } 127 128 129 $stmt->execute(); 130 131 $data_meta = null; 132 133 if($stmt_all = $pdo->query("SELECT FOUND_ROWS() AS 'all'")){ 134 $data_meta = $stmt_all->fetch(); 135 136 137 } 138 139 if(!$data_meta){ 140 exit("Failed to query FOUND_ROWS()."); 141 } 142 143 $all_data_length = (int)$data_meta["all"]; 144 145 146 147 if($all_data_length > $offset){ 148 $cnt = 1; 149 $start = $offset + 1; // 開始位置 150 $end = min($offset + $page_articles, $all_data_length); // 終了位置 151 $current_offset = $start == $end ? $start : "{$start}{$end}"; // 現在の位置 152 153 print "[{$page_number}ページ目の検索結果]\n"; 154 print "{$all_data_length} 件中 {$current_offset} 件を表示しています。\n\n<br>"; 155 156 157 //ここで保存 $session変数とかでセッションとかで保存すれば 158 159 160 while($data = $stmt->fetch(PDO::FETCH_ASSOC)){ 161 //print $cnt++ . "つ目の検索結果:\n"; 162 //print_r($data); 163 164 $pdf = $data['PDFURL']; 165 //ファイル名の後ろから4文字を削除 166 $pdf2 = substr($pdf, 46, -4); 167 168 //urlを接続しながら吐き出し 169 $url = "<a href='"; 170 171 print($url.$pdf."'>".$pdf2."</a><br>"); 172 //print("<br>".$data['PDFURL']."<br>"); 173 } 174 175 176 } 177 else{ 178 print " 検索条件に該当する企業はありませんでした。 179 条件を変更してもう一度検索してください。"; 180 /* 181 while($data = $stmt->fetch(PDO::FETCH_ASSOC)){ 182 print $cnt++ . "つ目の検索結果:\n"; 183 //print_r($data); // 184 185 $pdf = $data['PDFURL']; 186 //ファイル名の後ろから4文字を削除 187 //pdf2 = substr($pdf, 34, -4); 188 189 //urlを接続しながら吐き出し 190 //$url = "<a href='"; 191 192 //print($url.$data['備考欄']."'>".$pdf2."</a><br>"); 193 print("<br>".$data['PDFURL']."<br>"); 194 195 196 } 197 */ 198 } 199} 200?> 201 202 <p>現在 203 <?php 204 205 echo $page_number; 206 $maxpage = ceil($all_data_length / $page_articles); 207 //print($maxpage); 208 209 210 ?> 211 ページ目です。</p><br> 212 213 <?php 214 215 if (1 < $page_number){ 216 print("<a href='?search={$raw_keyword}&page=".($page_number-1)."'>前のページへ | </a>"); 217 218 } 219 220 221 if ($page_number < $maxpage){ 222 223 print("<a href='?search={$raw_keyword}&page=".($page_number+1)."'>次のページへ</a>"); 224 225 } 226 227 228 ?> 229 230</body> 231</html>

イメージ説明

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

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

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

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

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

kei344

2017/08/23 10:11

「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを、出ているエラーなどと併せて、具体的に記述されたほうが回答を得られやすいと思います。
otokichi_

2017/08/23 13:55

やりたい事は追記いたしました。何がどのように...。根本的にわかってないのかもしれませんね。
kei344

2017/08/23 14:02

「したいこと」も必要ですが、「どこまでできているのか」と、「何をしたときに」「どうなると思って」「どうなったのか(ならなかったのか)」をかかれてはいかがでしょう。
guest

回答2

0

phpで任意のグルーピングをした選択肢にチェックボックスを利用するなら
nameを揃えて「[]」を末尾につけるとよいでしょう

HTML

1<form method="post"> 2<input type="checkbox" name="search[]" value="東京都" ><label>東京都</label><br> 3<input type="checkbox" name="search[]" value="大阪府"><label>大阪府</label><br> 4<input type="checkbox" name="search[]" value="愛知県"><label>愛知県</label><br> 5<input type="checkbox" name="search[]" value="福岡県"><label>福岡県</label><br> 6<input type="checkbox" name="search[]" value="海外"><label>海外</label><br> 7<input type="submit" value="go"> 8</form> 9<?PHP 10$search=filter_input(INPUT_POST,'search',FILTER_DEFAULT,['flags'=>FILTER_REQUIRE_ARRAY]); 11print_r($search); 12?>

これだけで相当楽になります
フリーワードの検索は完全一致ではない場合効率がそうとう悪くなりますので注意下さい
PDOをご利用でしたらあとはprepare処理にデータを渡すだけです

投稿2017/08/23 10:35

yambejp

総合スコア114572

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

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

otokichi_

2017/08/23 13:57

ご回答ありがとうございます。これはグルーピングしてる場合ですよね?? 頑張ってやってみたのですが思うようにできなくて残念です。。。
yambejp

2017/08/24 00:18

$raw_keyword = $_GET["search"]; としているのを見る限り、search1-6をここで受け取ろうとしているのではないのですか? 一般にそのような処理の仕方がグルーピングの一つの手法となります 難しいようならもっと簡素な例から始められることをお勧めします。 たとえばフォームから値をうけとるだけとか 所定の値つかってDBからデータを抽出するだけとか・・・
guest

0

ベストアンサー

2種類の独立な条件を用いた絞り込み検索の実装というケースになります。質問者様の場合、$where変数が第一条件(フリーワード検索)なので、新たに$where_areasという変数で第二条件である所在地の絞り込みを実装しました。提示コードをできるだけ継承し、手続き的に書いています。以下のポイントを確認しておいてください。

  • ユーザーがチェックした都道府県名を配列としてPHPに投げる際、inputタグのname属性は area[] のような形でパラメータ名を指定することにより、$_GET["area"] が配列になる
  • 第一条件と第二条件はAND検索になるよう、where句の組み立てを行う

おまけですが、検索結果を表示するページに都道府県の選択状態が反映されるようにしています。また、流し読みしただけでも、受け取った文字列をそのまま出力するなどの問題点が見受けられます。プロダクトとして運用する際は十分ご注意下さいね。以下の点を注意しておきます。

  • ページ数を求める過程のどこかでゼロ除算が発生しているっぽい
  • formタグのmethod属性はgetではなくGETにしましょう
  • "ファイル名の後ろから4文字を削除" している箇所で、substr関数の第2引数は0のはず
  • 海外の判定が面倒なのでテーブル設計を見直したほうがいい(たとえばJIS都道府県コードで管理する等)
  • LIKE句においてワイルドカードのエスケープがされていない

php

1<?php 2 3$database = 'mysql:dbname=trainning'; 4$host = 'localhost'; 5$username = 'trainning'; 6$password = 'password'; 7$table_name = 'tablename'; 8 9$options = array( 10 PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8', 11); 12 13try{ 14 15 $pdo = new PDO($database, $username, $password, $options); 16 $pdo->query('SET NAMES utf8'); 17 print('<br>'); 18 19 if ($pdo == null){ 20 21 print('接続に失敗しました。<br>'); 22 23 } 24 25 $pdo->query('SET NAMES utf8'); 26 27 28}catch (PDOException $e){ 29 print('Error:'.$e->getMessage()); 30 die(); 31} 32 33/* 追加箇所1: GETパラメータにareasがあればそれを使う */ 34$areas = !empty($_GET["area"]) && is_array($_GET["area"]) ? array_values($_GET["area"]) : array(); 35 36?> 37 38<html> 39<head> 40 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 41 <title>search engine1.1</title> 42 43</head> 44 45<body> 46 47 <center><h1>search engine1.1</h1> 48 49 <form action="" method="get"> 50 51 <?php 52 /* 追加箇所2: 予め都道府県のリストを用意しておく */ 53 $predefined_areas = array("東京都", "大阪府", "愛知県", "福岡県", "北海道"); 54 foreach($predefined_areas as $area): 55 $checked = in_array($area, $areas) ? "checked" : ""; 56 ?> 57 <input type="checkbox" name="area[]" value="<?=$area?>" <?=$checked?>><label><?=$area?></label><br> 58 <?php 59 endforeach; 60 ?> 61 62 <p><input type="search" name="search" size="30" maxlength="255"placeholder="Search..."> 63 <input type="submit" value="検索"></p> 64 65 </form> 66 67 68 </center> 69 70 71 <?php 72 $search_type_and = false; 73 $raw_keyword = $_GET["search"]; 74 print("検索したキーワード [ ".$raw_keyword." ]<br>"); 75 76 //文字入力があれば実行 77 if(null != $raw_keyword){ 78 79 if(isset($_GET["page"]) && preg_match("/^[0-9]+$/", $_GET["page"])){ 80 $page_number = (int)$_GET["page"]; 81 if($page_number <= 0) $page_number = 1; 82 } 83 else{ 84 $page_number = 1; 85 } 86 $page_articles = 10; // 1ページに表示する件数(定数) 87 $offset = ($page_number - 1) * $page_articles; // オフセットを計算 88 89 90 $keywords = explode(" ", trim(str_replace(" ", " ", $raw_keyword))); 91 92 $target_columns = array( 93 94 "番号", 95 "企業名", 96 "ヨミガナ", 97 "上場企業", 98 "所在地", 99 "資本金", 100 "売上高", 101 "業種", 102 "事業内容", 103 "従業員数", 104 "備考欄", 105 "PDFURL" 106 107 ); 108 109 $where = array(); 110 111 foreach($target_columns as $index_column => $column){ // カラムのループ 112 $tmp = array(); 113 foreach($keywords as $index_keyword => $keyword){ // キーワードのループ 114 $tmp[] = "{$column} LIKE :keyword{$index_column}_{$index_keyword}"; 115 } 116 117 /* AND検索なら、すべてのキーワードが含まれるデータを対象とする 118 上のループで作ったLIKE文の配列を " AND " で繋げる */ 119 $where[] = join($search_type_and ? " AND " : " OR ", $tmp); 120 } 121 122 /* 追加箇所3: エリアの一覧を利用してSQL文を組み立てる */ 123 $where_area = array(); 124 foreach(array_keys($areas) as $key) { 125 $where_area[] = "`所在地` LIKE :area{$key}"; 126 } 127 128 /* 追加箇所4: 2種類の条件があるので、いいかんじにwhere句にする */ 129 /* prepare() 前まで書き直しています。 */ 130 $conditions = array(); 131 if($where){ 132 $condition[] = "(" . join(" OR ", $where) . ")"; 133 } 134 if($where_area){ 135 $condition[] = "(" . join(" OR ", $where_area) . ")"; 136 } 137 138 $conditionString = $condition ? join(" AND ", $condition) : "1"; 139 $query = "SELECT SQL_CALC_FOUND_ROWS * FROM {$table_name} WHERE {$conditionString} LIMIT {$offset}, {$page_articles}"; 140 141 $stmt = $pdo->prepare($query); 142 143 foreach($target_columns as $index_column => $column){ 144 foreach($keywords as $index_keyword => $keyword){ 145 if(!$stmt->bindValue(":keyword{$index_column}_{$index_keyword}", "%{$keyword}%")) { 146 exit("Failed to bind value: " . $keyword); 147 } 148 } 149 } 150 151 /* 追加箇所5: エリアの一覧をバインド */ 152 foreach($areas as $key => $area) { 153 if(!$stmt->bindValue(":area{$key}", "{$area}%")) { 154 exit("Failed to bind area"); 155 } 156 } 157 158 159 $stmt->execute(); 160 161 $data_meta = null; 162 163 if($stmt_all = $pdo->query("SELECT FOUND_ROWS() AS 'all'")){ 164 $data_meta = $stmt_all->fetch(); 165 166 167 } 168 169 if(!$data_meta){ 170 exit("Failed to query FOUND_ROWS()."); 171 } 172 173 $all_data_length = (int)$data_meta["all"]; 174 175 176 177 if($all_data_length > $offset){ 178 $cnt = 1; 179 $start = $offset + 1; // 開始位置 180 $end = min($offset + $page_articles, $all_data_length); // 終了位置 181 $current_offset = $start == $end ? $start : "{$start}{$end}"; // 現在の位置 182 183 print "[{$page_number}ページ目の検索結果]\n"; 184 print "{$all_data_length} 件中 {$current_offset} 件を表示しています。\n\n<br>"; 185 186 187 //ここで保存 $session変数とかでセッションとかで保存すれば 188 189 190 while($data = $stmt->fetch(PDO::FETCH_ASSOC)){ 191 //print $cnt++ . "つ目の検索結果:\n"; 192 //print_r($data); 193 194 $pdf = $data['PDFURL']; 195 //ファイル名の後ろから4文字を削除 196 $pdf2 = substr($pdf, 0, -4); 197 198 //urlを接続しながら吐き出し 199 $url = "<a href='"; 200 201 print($url.$pdf."'>".$pdf2."</a><br>"); 202 //print("<br>".$data['PDFURL']."<br>"); 203 } 204 205 206 } 207 else{ 208 print " 検索条件に該当する企業はありませんでした。 209 条件を変更してもう一度検索してください。"; 210 /* 211 while($data = $stmt->fetch(PDO::FETCH_ASSOC)){ 212 print $cnt++ . "つ目の検索結果:\n"; 213 //print_r($data); // 214 215 $pdf = $data['PDFURL']; 216 //ファイル名の後ろから4文字を削除 217 //pdf2 = substr($pdf, 34, -4); 218 219 //urlを接続しながら吐き出し 220 //$url = "<a href='"; 221 222 //print($url.$data['備考欄']."'>".$pdf2."</a><br>"); 223 print("<br>".$data['PDFURL']."<br>"); 224 225 226 } 227 */ 228 } 229 } 230 ?> 231 232 <p>現在 233 <?php 234 235 echo $page_number; 236 $maxpage = ceil($all_data_length / $page_articles); 237 //print($maxpage); 238 239 240 ?> 241 ページ目です。</p><br> 242 243 <?php 244 245 if (1 < $page_number){ 246 print("<a href='?search={$raw_keyword}&page=".($page_number-1)."'>前のページへ | </a>"); 247 248 } 249 250 251 if ($page_number < $maxpage){ 252 253 print("<a href='?search={$raw_keyword}&page=".($page_number+1)."'>次のページへ</a>"); 254 255 } 256 257 258 ?> 259 260</body> 261</html>

投稿2017/08/26 09:56

jinbe

総合スコア17

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問