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

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

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

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

Q&A

解決済

2回答

1918閲覧

PHPとSQLでフィルター付き検索画面を作りたい

nagata_

総合スコア12

MySQL

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

XAMPP

XAMPP(ザンプ)は、ウェブアプリケーションの実行に必要なフリーソフトウェアをパッケージングしたApacheディストリビューションです。 XAMPPひとつインストールするだけで、Apache、MySQL、PHP、Perlなどのソフトウェアと、 phpMyAdminなどの管理ツール、SQLiteなどのソフトウェアやライブラリモジュールなどを利用することが可能です。

0グッド

0クリップ

投稿2019/07/05 06:20

編集2019/07/09 05:28

util.phpのコード

<?php // XSS対策のためのHTMLエスケープ function es($data, $charset='UTF-8'){ // $dataが配列のとき if (is_array($data)){ // 再帰呼び出し return array_map(__METHOD__, $data); } else { // HTMLエスケープを行う return htmlspecialchars($data, ENT_QUOTES, $charset); } } // 配列の文字エンコードのチェックを行う function cken(array $data){ $result = true; foreach ($data as $key => $value) { if (is_array($value)){ // 含まれている値が配列のとき文字列に連結する $value = implode("", $value); } if (!mb_check_encoding($value)){ // 文字エンコードが一致しないとき $result = false; // foreachでの走査をブレイクする break; } } return $result; } //

easy.phpのコード### > ヘディングのテキスト

<?php require_once("util.php"); $gobackURL = "easy.php"; if (!cken($_POST)){ header("Location:{$gobackURL}"); exit(); } $user = "iPhoneuser"; $password = "iPhoneuser1020"; $dbName ="apple_product"; $host = "localhost:3306"; $dsn = "mysql:host={$host};dbname={$dbName}; charset=utf8"; ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>名前検索</title> <link href="P_NPL2130A.css" rel="stylesheet"> </head> <SCRIPT LANGUAGE="JavaScript"> </SCRIPT> <body> <form method="POST" action="<?php echo es($_SERVER['SCRIPT_NAME']); ?>"> <table border="1"> <tr> <td>機種名</td> <td> <input type="text" name="P_KISYUMEI" placeholder="機種名を入力してください。" value="<?php echo $P_KISYUMEI ?>"></td> <td rowspan="7" align="center" valign="middle">&nbsp;<input type="submit" value="SEARCH">&nbsp;</td> </tr> <tr> <td>シリーズ</td> <td> <table> <tr> <td><input type="checkbox" value="iPhone3" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone3</td> <td><input type="checkbox" value="iPhone4" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone4</td> <td><input type="checkbox" value="iPhone5" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone5</td> <td><input type="checkbox" value="iPhone6" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone6</td> </tr> <tr> <td><input type="checkbox" value="iPhone7" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone7</td> <td><input type="checkbox" value="iPhone8" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhone8</td> <td><input type="checkbox" value="iPhoneX" name="P_SERIES[]" <?php echo isset($_POST['P_SERIES']) ?>>iPhoneX</td> </tr> </table> </td> </tr> </table> </form> <?php try{ $pdo = new PDO($dsn, $user, $password); // プリペアドステートメントのエミュレーションを無効にする $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // 例外がスローされる設定にする $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $whereCollection = []; if(!empty($_POST['P_KISYUMEI '])){ $whereCollection[] = ' P_KISYUMEI LIKE :P_KISYUMEI '; } //75行目 if(count($_POST['P_SERIES']) > 0){ $series = []; for($i=0;$i<count($_POST['P_SERIES']);$i++){ $series[] = ':SERIES'.$i; } $whereCollection[] = ' P_SERIES IN ('.implode(',',$series).') '; } $where = count($whereCollection)>0? " where ".implode(" and ",$whereCollection):""; $sql = "SELECT * FROM iphone_spec ".$where; //チェック用 echo $where; $stm = $pdo->prepare($sql); if(!empty($_POST['P_KISYUMEI '])){ $stm->bindValue(':P_KISYUMEI', "%{$P_KISYUMEI}%", PDO::PARAM_STR); } //92行目 if(count($_POST['P_SERIES']) > 0){ for($i=0;$i<count($_POST['P_SERIES']);$i++){ $stm->bindValue(':SERIES'.$i, $_POST['P_SERIES'][$i], PDO::PARAM_STR); } } $stm->execute(); // 結果の取得(連想配列で受け取る) $result = $stm->fetchAll(PDO::FETCH_ASSOC); echo count($result)."件の機種が見つかりました。"; if(count($result)>0){ //echo "機種名に「{$P_KISYUMEI}」が含まれているレコード"; // テーブルのタイトル行 echo "<table border=1>"; echo "<thead><tr>"; echo "<th bgcolor='#cccccc'>", "No.", "</th>"; echo "<th bgcolor='#cccccc'>", "詳細", "</th>"; echo "<th bgcolor='#cccccc'>", "機種名", "</th>"; echo "<th bgcolor='#cccccc'>", "シリーズ", "</th>"; echo "<th bgcolor='#cccccc'>", "CPU", "</th>"; echo "</tr></thead>"; // 値を取り出して行に表示する echo "<tbody>"; foreach ($result as $key => $row){ // 1行ずつテーブルに入れる $keys = $key+1; echo "<tr>"; echo "<td bgcolor='#ffffff'>{$keys}</td>"; echo "<td bgcolor='#ffffff'></td>"; echo "<td bgcolor='#ffffff'>", es($row['P_KISYUMEI']), "</td>"; echo "<td bgcolor='#ffffff'>", es($row['P_SERIES']), "</td>"; echo "<td bgcolor='#ffffff'>", es($row['CPU']), "</td>"; echo "</tr>"; } echo "</tbody>"; echo "</table>"; } else { echo "機種名に「{$P_KISYUMEI}」は見つかりませんでした。"; } }catch (Exception $e) { echo '<span class="error">エラーがありました。</span><br>'; echo $e->getMessage(); } ?> <hr> <p><a href="<?php echo $gobackURL ?>">CLEAR</a></p> </body> </html>

イメージ説明

発生している問題・エラーメッセージ

シリーズのチェックボックスにチェックを入れると正常に動作します。 しかし機種名を入力すると、画像のようなエラーがでます。 また、やりたいことととして 機種名に「iPhone」、シリーズをiPhone3,iPhone4にチェックを入れると iPhone3,iPhone3GS,iPhone4,iPhone4sが検索結果に出したいです。 現状では、エラーがでてしまう状況でコーディング中です。

試したこと

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

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

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

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

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

guest

回答2

0

ノーチェックですが

PHP

1 // SQL文を作る 2 $sql = "SELECT * FROM iphone_spec WHERE P_KISYUMEI LIKE(:P_KISYUMEI).$whereSql"; 3 // プリペアドステートメントを作る 4 $stm = $pdo->prepare($sql); 5 // プレースホルダに値をバインドする 6 $stm->bindValue(':P_KISYUMEI', "%{$P_KISYUMEI}%", PDO::PARAM_STR); 7 $stm->bindValue(':P_SERIES', "%{$P_SERIES}%", PDO::PARAM_STR); 8 // SQL文を実行する 9 $stm->execute();

SQL文にP_SERIESのプレースホルダ無いです。
SQL文に:P_SERIESがないと$stm->bindValue(':P_SERIES', "%{$P_SERIES}%", PDO::PARAM_STR);を指定してるのでエラーになります
また.$whereSql.は必要でしょうか(スペースまたはLIKE(:P_KISYUMEI)" . $whereSql;こう?

投稿2019/07/05 06:34

編集2019/07/05 07:31
rururu3

総合スコア5545

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

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

nagata_

2019/07/05 06:49

ご指摘の通り書き直しましたが、うまくいきませんでした・・・。P_SIRIESの配列のつくり方から不安があるので、間違えているところが多いかもしれません・・・。 ちなみにエラーは SQLSTATE[HY093]: Invalid parameter number: parameter was not defined とでています。
rururu3

2019/07/05 07:29

文章間違えてました P_KISYUMEIのプレースホルダ ではなく P_SERIESのプレースホルダないですよね・・・が正しいです
guest

0

ベストアンサー

:P_SERIESがSQLとして投入されるのが、下記を通ったとき

php

1 if (!empty($params['P_SERIES'])) { 2 $where[] = 'P_SERIES = '. $params['P_SIRIES']; 3 }

ですが、名前付きパラメータではなく値がそのままセットされているように思います。

名前付きパラメータにしたうえで、同条件(if (!empty($params['P_SERIES'])) {)にて:P_SERIESに対してbindValueすれば良いのではないでしょうか。

php

1$sql = "SELECT * FROM iphone_spec WHERE P_KISYUMEI LIKE(:P_KISYUMEI).$whereSql";

LIKEに()つけても効かないように思います(未確認)

文字列連結部分もおかしいので

こう

PHP

1$sql = "SELECT * FROM iphone_spec WHERE P_KISYUMEI LIKE :P_KISYUMEI ".$whereSql;

またはこうでは

PHP

1$sql = "SELECT * FROM iphone_spec WHERE P_KISYUMEI LIKE :P_KISYUMEI {$whereSql}";

いずれにしても、「実際に出来上がる予定のSQL」を直接DBに対して実行して想定通りの動作をするかは確認してくださいね。

コードフォーマットしたうえで色々と気になる点を指摘

php

1<?php 2require_once ("util.php"); 3$gobackURL = "iPhone_Search.php"; 4 5if (! cken($_POST)) { 6 header("Location:{$gobackURL}"); 7 exit(); 8} 9 10$user = "******"; 11$password = "*****"; 12$dbName = "*******"; //どこにも使われてない 13$host = "*******"; //どこにも使われてない 14$dsn = "*****"; 15?> 16 17<?php 18// POSTされた値を取り出す 19if (isSet($_POST["P_KISYUMEI"])) { 20 // 数値かどうか確認する 21 $isNum = ctype_alnum($_POST["P_KISYUMEI"]); 22 if ($isNum) { 23 // 数値ならば計算式とフォーム表示の値で使う 24 $P_KISYUMEI = $_POST["P_KISYUMEI"]; 25 $error = ""; //どこにも使われてない 26 } else { 27 $P_KISYUMEI = ""; 28 $error = '<span class="error">←数値を入力してください。</span>'; //どこにも使われてない 29 } 30} else { 31 // POSTされた値がないとき 32 $isNum = false; 33 $P_KISYUMEI = ""; 34 $error = ""; //どこにも使われてない 35} 36 37function POSTiPhoneData($params) 38{ 39 $where = []; 40 if (! empty($params['P_SERIES'])) { 41 $where[] = 'P_SERIES = ' . $params['P_SIRIES']; 42 } 43 if ($where) { 44 $whereSql = implode(' AND ', $where); // returnしてない 45 } 46} 47$P_SERIES = POSTiPhoneData($params); //$paramsは未定義 48//returnしてないのでnullが入ってるのでは 49?> 50 51//中略 52<body> 53 54 55 <div class="main"> 56<!-- </form>がないです --> 57 <form method="POST" 58 action="<?php echo es($_SERVER['SCRIPT_NAME']); ?>"> 59 <table border="1"> 60 <tr valign="top"> 61 <td class="KOUMOKU">製品</td> 62 <td bgcolor="#eeeeee"></td> 63 <td class="KOUMOKU" rowspan="7" align="center" valign="middle">&nbsp;<input 64 type="submit" value="SEARCH">&nbsp; 65 </td> 66 </tr> 67 <tr valign="top"> 68 <td class="KOUMOKU">機種名</td> 69 <td bgcolor="#eeeeee">&nbsp; <input type="text" name="P_KISYUMEI" 70 placeholder="機種名を入力してください。" value="<?php echo $P_KISYUMEI ?>"> 71 </td> 72 </tr> 73 <tr valign="top"> 74 <td class="KOUMOKU">シリーズ<br>※未指定:全て対象<br> <input type="button" 75 name="srclear" value="全解除" onClick="sr_clear(this.form)" 76 style="font-size: 9pt; HEIGHT =18px; WIDTH: 60px;"> 77 </td> 78 <td bgcolor="#eeeeee"> 79 <table> 80 <tr valign="top"> 81 <td width="90"><input type="checkbox" value="iPhone3" 82 name="P_SERIES" <?php echo isset($_POST['P_SERIES']) ?>>iPhone3</td> 83 <td width="90"><input type="checkbox" value="iPhone4" 84 name="P_SERIES" <?php echo isset($_POST['P_SERIES']) ?>>iPhone4</td> 85 <td width="90"><input type="checkbox" value="iPhone5" 86 name="P_SERIES" <?php echo isset($_POST['P_SERIES']) ?>>iPhone5</td> 87 <td width="90"><input type="checkbox" value="iPhone6" 88 name="P_SERIES" <?php echo isset($_POST['P_SERIES']) ?>>iPhone6</td> 89 </tr> 90 <tr valign="top"> 91 <td><input type="checkbox" value="iPhone7" name="P_SERIES" 92 <?php echo isset($_POST['P_SERIES']) ?>>iPhone7</td> 93 <td><input type="checkbox" value="iPhone8" name="P_SERIES" 94 <?php echo isset($_POST['P_SERIES']) ?>>iPhone8</td> 95 <td><input type="checkbox" value="iPhoneX" name="P_SERIES" 96 <?php echo isset($_POST['P_SERIES']) ?>>iPhoneX</td> 97 </tr> 98<!-- これだとcheckboxだけど任意数送信できません --> 99 </table> 100 </td> 101 </tr> 102 ![イメージ説明](37aa018366d48ac3378cdbd1637120ac.png) <!-- コードブロック内でマークダウン効かないので外にだしてください --> 103 <tr valign="top"> 104 <td class="KOUMOKU">ストレージ<br>※未指定:全て対象<br> <input type="button" 105 name="smclear" value="全解除" onClick="sm_clear(this.form)" 106 style="font-size: 9pt; HEIGHT =18px; WIDTH: 60px;"> 107 </td> 108 109//中略 110 111 <?php 112if ($isNum) { 113 114 $P_KISYUMEI = $_POST["P_KISYUMEI"]; 115 // MySQLデータベースに接続する 116 try { 117 $pdo = new PDO($dsn, $user, $password); 118 // プリペアドステートメントのエミュレーションを無効にする 119 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 120 // 例外がスローされる設定にする 121 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 122 // SQL文を作る 123 $sql = "SELECT * FROM iphone_spec WHERE P_KISYUMEI LIKE(:P_KISYUMEI).$whereSql"; //$whereSqlは未定義 P_KISYUMEIは絶対に検索するの? 124 // プリペアドステートメントを作る 125 $stm = $pdo->prepare($sql); 126 // プレースホルダに値をバインドする 127 $stm->bindValue(':P_KISYUMEI', "%{$P_KISYUMEI}%", PDO::PARAM_STR);//検索条件がない場合もバインドする? 128 $stm->bindValue(':P_SERIES', "%{$P_SERIES}%", PDO::PARAM_STR);///チェックボックスなのにlikeでいい?「どれかに一致する」になるのでは? 129 // SQL文を実行する 130 $stm->execute(); 131 // 結果の取得(連想配列で受け取る) 132 $result = $stm->fetchAll(PDO::FETCH_ASSOC); 133 134//後略

未定義の変数とかどこにも使われていない変数についてはIDE(Eclipseなど)ですぐ見つけられます。
いずれにしても最低限、コードフォーマット機能の付いたエディタを使いましょう。

で、どうすべきか

動作確認してませんが、大きくは2か所修正が必要に思います。

下記は一式不要

php

1function POSTiPhoneData($params) 2{ 3 $where = []; 4 if (! empty($params['P_SERIES'])) { 5 $where[] = 'P_SERIES = ' . $params['P_SIRIES']; 6 } 7 if ($where) { 8 $whereSql = implode(' AND ', $where); 9 } 10} 11$P_SERIES = POSTiPhoneData($params);

なぜなら、SQL文の本文との距離が遠すぎるから。

HTMLの下記を変更

html

1name="P_SERIES" 23name="P_SERIES[]"

SQL作ってbindするところを下記のようにする

php

1$whereCollection = []; 2if(!empty($_POST['P_KISYUMEI '])){ 3 $whereCollection[] = ' P_KISYUMEI LIKE :P_KISYUMEI '; 4} 5if(count($_POST['P_SIRIES']) > 0){ 6 $siries = []; 7 for($i=0;$i<count($_POST['P_SIRIES']);$i++){ 8 $siries[] = ':SIRIES'.$i; 9 } 10 $whereCollection[] = ' P_SIRIES IN ('.implode(',',$siries).') '; 11} 12 13$where = count($whereCollection)>0? " where ".implode(" and ",$whereCollection):""; 14$sql = "SELECT * FROM iphone_spec ".$where; 15 16 17$stm = $pdo->prepare($sql); 18 19if(!empty($_POST['P_KISYUMEI '])){ 20 $stm->bindValue(':P_KISYUMEI', "%{$P_KISYUMEI}%", PDO::PARAM_STR); 21} 22if(count($_POST['P_SIRIES']) > 0){ 23 for($i=0;$i<count($_POST['P_SIRIES']);$i++){ 24 $stm->bindValue(':SIRIES'.$i, $_POST['P_SIRIES'][$i], PDO::PARAM_STR); 25 } 26} 27$stm->execute();

投稿2019/07/05 06:31

編集2019/07/05 07:46
m.ts10806

総合スコア80854

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

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

nagata_

2019/07/05 06:52

「名前付きパラメータではなく値がそのままセットされているように思います。名前付きパラメータにしたうえで、同条件(if (!empty($params['P_SERIES'])) {)にて:P_SERIESに対してbindValueすれば良いのではないでしょうか。」 申し訳ありません。まだまだ初心者なのでおっしゃっている用語が良く分かっていません・・・。よろしければSQL文のようなコード例を書いていただけると助かります。 文字連結の方は理解できました。ありがとうございます。
m.ts10806

2019/07/05 07:34

だいぶ書き直す必要がありそうですが、ざっと書き出しました。 コードフォーマットは必須です。(読みづらいので)
nagata_

2019/07/05 09:53

丁寧回答ありがとうございます。 いただいたもの回答を参考に修正してみます!
nagata_

2019/07/09 05:17

はい、結論から言うとエラーが出たままだったので、コードをシンプルに書き直してみました。 しかし、それでもエラーが残ったままだったので、現在もコーディング中です。 一応、質問も更新しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問