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

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

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

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

Q&A

2回答

1786閲覧

複数キーワード検索をしたい。

tshigeo2000

総合スコア0

MySQL

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

0グッド

1クリップ

投稿2021/01/21 13:44

編集2021/01/25 12:03

前提・実現したいこと

検索フォームを利用して、MySQLサーバーから複数のキーワード検索を行いたいです。
検索の条件として、カラム毎に検索フォームが設けられている方法ではなくて、
1つの検索フォームにて、2つ以上のカラムを(複数のキーワードを検索)検索する方法です。
例えば、下記のテーブルから、エアコン有など、1つのカラムでの検索はできますが、
【エアコン有 プリウス】 という2つのカラム検索が出来ません。
(【】は、一つの検索フォームとして解釈してください。)
エアコン有 | カローラ | 新車|
エアコン有 | カローラ | 新車|
エアコン無 | カローラ | 新車|
エアコン有 | カローラ | 中古|
エアコン有 | カローラ | 中古|
エアコン無 | プリウス | 新車|
エアコン有 | プリウス | 新車|
エアコン有 | プリウス | 新車|
エアコン有 | プリウス | 新車|
エアコン無 | プリウス | 中古|
エアコン有 | プリウス | 中古|
エアコン有 | プリウス | 中古|

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

未入力です検索結果は0件です。 検索結果がありません。と表示されてしまいます。

該当のソースコード

<?php session_start(); ?> <!DOCTYPE html> <html lang="ja"> <head> <title>PHPのテスト</title> </head> <body> <hr> 会員名簿一覧 <hr> [ <a href="form.html">新規登録</a>] <br> <form name="form1" method="post" action="list.php"> 名前:<input type="text" name="search_key"><input type="submit" value="検索する"> </form> <?php require_once("MYDB.php"); $pdo = db_connect(); if(empty($_PORTS['check_data'])){ echo "未入力です"; } // 削除処理 削除するデータ項目fに「2」のフラグを立てる。データそのものを削除しない方法 if(isset($_GET['action']) && $_GET['action'] == 'delete' && $_GET['id'] > 0 ){ try { $pdo->beginTransaction(); $id = $_GET['id']; $sql = "DELETE FROM test WHERE id = :id"; $sql = "UPDATE test SET f='2' WHERE id = :id"; $stmh = $pdo->prepare($sql); $stmh->bindValue(':id', $id, PDO::PARAM_INT ); $stmh->execute(); $pdo->commit(); print "データを" . $stmh->rowCount() . "件、削除しました。<br>"; } catch (PDOException $Exception) { $pdo->rollBack(); print "エラー:" . $Exception->getMessage(); } } // 挿入処理 if(isset($_POST['action']) && $_POST['action'] == 'insert'){ try { $pdo->beginTransaction(); $sql = "INSERT INTO test (test1, test2, test3) VALUES ( :test1, :test2, :test3 )"; $stmh = $pdo->prepare($sql); $stmh->bindValue(':test1', $_POST['test1'], PDO::PARAM_STR ); $stmh->bindValue(':test2', $_POST['test2'], PDO::PARAM_STR ); $stmh->bindValue(':test3', $_POST['test3'], PDO::PARAM_STR ); $stmh->execute(); $pdo->commit(); print "データを" . $stmh->rowCount() . "件、挿入しました。<br>"; } catch (PDOException $Exception) { $pdo->rollBack(); print "エラー:" . $Exception->getMessage(); } } // 更新処理 if(isset($_POST['action']) && $_POST['action'] == 'update'){ // セッション変数よりidを受け取ります $id = $_SESSION['id']; try { $pdo->beginTransaction(); $sql = "UPDATE test SET test1 = :test1, test2 = :test2, test3 = :test3 WHERE id = :id"; $stmh = $pdo->prepare($sql); $stmh->bindValue(':test1', $_POST['test1'], PDO::PARAM_STR ); $stmh->bindValue(':test2', $_POST['test2'], PDO::PARAM_STR ); $stmh->bindValue(':test3', $_POST['test3'], PDO::PARAM_STR ); $stmh->bindValue(':id', $id, PDO::PARAM_INT ); $stmh->execute(); $pdo->commit(); print "データを" . $stmh->rowCount() . "件、更新しました。<br>"; } catch (PDOException $Exception) { $pdo->rollBack(); print "エラー:" . $Exception->getMessage(); } // 使用したセッション変数を削除する unset($_SESSION['id']); } // 検索および現在の全データを表示します try { if(isset($_POST['search_key']) && $_POST['search_key'] != ""){ $search_key = '%' . $_POST['search_key'] . '%'; $sql= "SELECT * FROM test WHERE test1 like :test1 OR test2 like :test2 OR test3 like :test3"; $stmh = $pdo->prepare($sql); $stmh->bindValue(':test1', $search_key, PDO::PARAM_STR ); $stmh->bindValue(':test2', $search_key, PDO::PARAM_STR ); $stmh->bindValue(':test3', $search_key, PDO::PARAM_STR ); $stmh->execute(); }else{ // $sql= "SELECT * FROM test "; // 削除フラグ「2」となっているものを表示させない。「2」以外のものを表示させる。 $sql= "SELECT * FROM test WHERE f <>2"; $stmh = $pdo->query($sql); } $count = $stmh->rowCount(); print "検索結果は" . $count . "件です。<br>"; } catch (PDOException $Exception) { print "エラー:" . $Exception->getMessage(); } if($count < 1){ print "検索結果がありません。<br>"; }else{ ?> <table border="1"> <tbody> <tr><th>番号</th><th>test1</th><th>test2</th><th>test3</th><th>&nbsp;</th><th>&nbsp;</th></tr> <?php while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) { ?> <tr> <td><?=htmlspecialchars($row['id'], ENT_QUOTES)?></td> <td><?=htmlspecialchars($row['test1'], ENT_QUOTES)?></td> <td><?=htmlspecialchars($row['test2'], ENT_QUOTES)?></td> <td><?=htmlspecialchars($row['test3'], ENT_QUOTES)?></td> <td><a href=updateform.php?id=<?=htmlspecialchars($row['id'], ENT_QUOTES)?>>更新</a></td> <td><a href=list.php?action=delete&id=<?=htmlspecialchars($row['id'], ENT_QUOTES)?>>削除</a></td> </tr> <?php } ?> </tbody></table> <?php } ?> </body> </html>

試したこと

検索の組み立てがイメージ出来ません。(初心者で申し訳ありません。)

Windows10にてapacheとMySQLを稼働
mysql Ver 15.1 Distrib 10.4.14-MariaDB
PHP 7.4.11 (cli)
ここにより詳細な情報を記載してください。

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

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

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

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

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

m.ts10806

2021/01/21 21:39

PHP SQL 動的 とかで調べて出てくる情報はヒントになりませんか?
eazyRe

2021/01/23 15:06

回答に対するコメント内の追加のご質問ですが、内容を理解できませんでした。 「うまくつかめません」のような抽象的な表現は回答者によって解釈が異なるので、具体的な表現に修正することをお勧めします。 また文脈上、何に対しての「良い案」を求めているのかわかりませんでした。
tshigeo2000

2021/01/24 01:28

ご指摘について、不十分な説明ですみません。やりたい事は、2カラム以上の複数キーワードの検索を 行いたいのですが、最初に頂いた回答ですと、各入力フォームにてキーワードの入力となっていますが、 私が行いたいのは、1つの入力フォームにて2カラム以上の複数キーワードの検索を行いたいのです。 カラムという表現が適切なのかわかりませんが、一つの入力フォームに、「エアコン有  プリウス」と入力して、検索する方法が知りたいです。よろしくお願いいたします。
m.ts10806

2021/01/24 01:31

質問は編集できますので。
tshigeo2000

2021/01/24 05:48

ご指摘有難うございます。質問内容を修正致しました。
guest

回答2

0

コードが、部分的に初心者っぽくないのですが、どちらかを参考にしていますか?
(微妙に実務に耐えられるレベルではないので回答書くのがちょっと怖い)

参考があるのであれば、追記しておいてください。

本件ですが、主な流れは以下の通りです。
1.$_POST['search_key']をパースする
2.SQL にて WHERE をパースした情報にもとづき動的に構築する

1 は半角スペースで限定してしまうのであれば、それほど難しくありません。
2 はプレースフォルダを使用しようとするとちょっと工夫が必要です。
いくつか実現方法があるので、調べてみて安全性を確認すると良いです。

余談)
サンプルコードのような例であれば、個人的には余計なワードを投入されないように、プルダウンメニューで選択させたいです。

投稿2021/01/24 23:44

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tshigeo2000

2021/01/25 11:50

ご回答有難うございます。すみません。私自身初心者です。下記の本を参考に出来るところまで 作成しました。PCの環境を記載しておりませんでしたので、追記します。 あくまでも、テスト環境用のPCにて検証をしています。 https://book.mynavi.jp/ec/products/detail/id=87661
退会済みユーザー

退会済みユーザー

2021/01/25 12:31

参考書のコードですね。それでレベル感がちぐはぐなんですね。 理解しました。 動的な WHERE の生成は、こちらのサイトの実装方法が参考になると思います。 PHPで動的なSQLでプリペアドステートメントな一例(本題は、IN句でどうやってプリペアるか) https://gallu.hatenadiary.jp/entry/20171104/p1 提示先は IN 句なのでちょっと読み替えが必要ですが、少し悩んでみてください。 結構面白いところです。
tshigeo2000

2021/01/25 12:42

参考リンク有難うございます。中々、この辺の情報がインターネットでは探し出せなくて苦労しました。 書籍もそこまで、深堀して説明していないので、色々と悩んで、記載の本を購入しました。
guest

0

ポスト変数のタイプミスがあります。

if(empty($_PORTS['check_data'])){ echo "未入力です"; }

【追記 2021/1/24 15:27】
以降の記載について、質問者とのやり取りで解釈が誤っていることがわかりました。
× 1:1でカラムに対応するテキストフィールドから1つのキーワードを入力
○ 1つのテキストフィールドから複数のキーワードを入力
以下は質問者のやりたいことと異なりますので、ご注意ください。

やりたいことを汲み取れているか不安ですが、下記に複数のカラム検索の例を載せます。
検索処理以外の部分については考慮していないので、ご注意ください。

■検索画面

<form name="form1" method="post" action="list.php"> エアコン有無:<input type="text" name="search_key[test1]"> 車種:<input type="text" name="search_key[test2]"> 新車/中古:<input type="text" name="search_key[test3]"> <input type="submit" value="検索する"> </form>

■検索処理

if(isset($_POST['search_key'])){ $sql = "SELECT * FROM test"; $sql_condition = []; $bind_list = []; foreach($_POST['search_key'] as $key => $value){ if($value != ""){ $sql_condition[] = $key . ' LIKE :' . $key; $bind_list[$key] = [ 'param' => ':'. $key, 'value' => '%' . $value . '%' ]; } } if(!empty($sql_condition)){ $sql .= " WHERE " . implode(" OR ", $sql_condition); }else{ $sql .= " WHERE f <> 2"; } $stmh = $pdo->prepare($sql); foreach($bind_list as $key => $bind){ $stmh->bindValue($bind['param'], $bind['value'], PDO::PARAM_STR); } $stmh->execute(); }else{ // $sql= "SELECT * FROM test "; // 削除フラグ「2」となっているものを表示させない。「2」以外のものを表示させる。 $sql = "SELECT * FROM test WHERE f <> 2"; $stmh = $pdo->query($sql); }

投稿2021/01/22 15:51

編集2021/01/24 06:27
eazyRe

総合スコア25

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

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

tshigeo2000

2021/01/23 09:30

ご回答有難うございます。まだまだスキル不足でわからないのですが、 ご指摘頂いた「ポスト変数のタイプミスがあります。」についてが理解出来ていません。 (ミスが分かっていないです。)検索画面のす作り有難うございます。検索処理についてですが、 私の説明不足で申し訳ありません。質問した内容のテーブルですと、2カラムを検索したときに、 「エアコン有 」「プリウス」キーワードの検索となるので、結果が5件になる様に、 考えておりましたが、上手く意図が伝わらずすみません。結果は、12件となってしまいました。 ここは、or ではなく、andが正解なのでしょうか?色々とすみませんが、よろしくお願いいたします。
eazyRe

2021/01/23 11:21

「ポスト変数」は「$_POST」のことです。 「タイプミス」は「キーボードからの入力の打ち間違い」のことです。 「$_POST」を使っているかよく見てみましょう。 また、検索画面で'check_data'に値をセットしていないので、毎回"未入力です"が出力されます。 $_POSTに何が入っているのか確認してみましょう。 SQLの条件が or か and のどちらが正解なのかは、やりたいこと(仕様)によって変わります。 and にしてみて、今回の期待する結果になるか確認してみましょう。
tshigeo2000

2021/01/23 12:52

ご指摘有難うございます。初歩的なミスをしておりました。再度見直してみます。 また、SQL条件については、仕様に合う箇所を模索してみます。 今回、カラム毎に、検索(入力フォーム)を分けてご教示頂きましたが、 1つのフォームで3カラムの検索がうまくつかめません。一つのフォームからtest1 test2 test3をそれぞれ、検索するイメージつなげてると思うのですが、良い案はありますか?度々申し訳ございません。 よろしくお願いいたします。
eazyRe

2021/01/24 07:34

根本的に解釈が誤っていたみたいですね。解釈の誤りを回答に追記しました。 元のソースと例を参考にすると、'エアコン有 プリウス'という文字列を3つのカラムから部分一致で検索していることになります。 各カラムの中に'エアコン有 プリウス'という文字列はないです。あるのは'エアコン有'や'プリウス'という文字列です。 まずは下記を念頭にご自身で試してみるといいかもしれません。 ①'エアコン有 プリウス'を'エアコン有'、'プリウス'という文字列に分離する(PHP)。 ②分離した各文字列を3つのカラムから部分一致で検索する(SQL)。 teratail内でも似たようなやり取りがありましたので、参考になると思います。 https://teratail.com/questions/75553 私からの回答は以上になります。
tshigeo2000

2021/01/24 14:34

ご回答、解釈の誤り追記有難うございます。 ご説明して頂きました内容(文字列の分離、分離後からの部分一致での検索)理解出来ました。 ご案内頂いた過去の回答を拝見しましたが、分離、部分一致での検索をどのようになっているのか、 仕組みが理解出来ませんでした。(まだまだ、単語?がわかりません。)インターネットで分離等の キーワードで検索してみましたが、わかりませんでした。もっとわかりやすいものはありますか? (スキル不足すみません。私の質問ソースを元に記載してもらえると助かります。)よろしくお願いいたします。
eazyRe

2021/01/24 22:09

> 単語?がわかりません。 おそらくPHPの組み込み関数のことですね。 わからないことを検索する際のおすすめのキーワードです。 「プログラミング 調べ方」→ 調べ方を知っておくと今後役に立つはずです。 「PHP 初心者 〇〇」→「PHP 初心者 組み込み関数」「PHP 初心者 文字列 分離」など 「MySQL 初心者 〇〇」→ 「MySQL 初心者 LIKE 複数」など 上記でもわからない場合は、わからないことを具体的にして細かく分けた後にteratailで個別に質問を投稿すると、それぞれの詳しい回答を得られるかもしれません。 現状ですと、今回取り組んでいる題材は少し難易度が高いように思います。 題材を変えて、初心者向けの解説が付いた参考書などに沿って進めるのも一つの手です。 ※あくまでも個人的な意見なので参考までに。
退会済みユーザー

退会済みユーザー

2021/01/25 12:31

ちゃんと見ているわけでなく、直観ですが(?!) ・インジェクションできそう $sql_condition[] = $key . ' LIKE :' . $key; ・$value に対しての '%_' 等のエスケープが足りてない 'value' => '%' . $value . '%' まぁ、サンプルだろうし、この辺はちゃんとやろうとするとめんどくさいんですよねぇ。。。
tshigeo2000

2021/01/25 12:51

PHPを扱った辞書?があればいいのですが、なかなか見つかりません。でも、地道に記載した本で 調べて理解するしかありません。基礎がないので、どこが間違えなのか、どこが相応しいのか、 わかりません。とりあえず、完成してから、一つ一つデバッグするだけです。
eazyRe

2021/01/26 12:01 編集

> te2jiさん ご指摘ありがとうございます。 仰るとおり、考慮が足りていませんでした。。 > tshigeo2000さん te2jiさんの回答で紹介されている記事と比較して、何が問題なのか調べると理解が深まると思います。 うまく動かないときこそデバッグすることで、どこが間違えなのか、どこが相応しいのか、だんだんと絞れてくると思います。 PHPの辞書は公式のドキュメントですかね。 最初はわかりにくいかと思いますが、いずれお世話になります。 例:explode — 文字列を文字列により分割する https://www.php.net/manual/ja/function.explode.php
tshigeo2000

2021/01/26 14:53

>eazyReさん 情報ありがとうございます。挫折しながら、読み込んでみたいと思います。 いきなり、レベルの高いものを作成しようとしていたみたいですね。 皆様からご案内頂いた情報をもとに、色々と試してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問