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

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

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

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

PHP

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

1回答

1126閲覧

phpでSQLのLIKEの値に複数の変数を代入したい

asianLad

総合スコア16

MySQL

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

PHP

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2021/04/29 07:57

1. やりたい・やりたかったこと

背景
カードゲームのDBを作っています。
DBのカード検索でテーブル(ユーザがブラウザ上で入力する項目)が4つあります。
name, attribute, type, numberの4つです。
issetで値の有無を確認して変数にattribute LIKE '$pro_attributeなどの値を入れたいです。
例えば4つ全て入っているときはsqlの変数数に入るコードは以下のようになります。
$sql_part_head="SELECT code,name,attribute,type,number FROM mst_product"LIKE "WHERE name LIKE '%$pro_name%'"
"attribute LIKE '%$pro_attribute%'"
"type LIKE '%$pro_type%'"
"number LIKE '%$pro_number%'"
(そもそもこれはSQL文として正しいのでしょうか?どのようにして検索ボックスでユーザーに入力された項目を連結してDBからデータをとれば良いのでしょうか?根本的に私の考えとアプローチが間違っていたら教えてください。)

2. 起きている問題やエラーメッセージ

以下のエラーメッセージが出力されます。

失敗:SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''WHERE name LIKE '%ドラゴン%''AND'number LIKE '%%''AND''AND''' at line 1

3. 関連するソースコード

対象のソースコードになります。

PHP

1<!DOCTYPE html> 2<html> 3<head> 4<meta charset="UTF-8"> 5<title>トレカDB</title> 6</head> 7<body> 8 9<?php 10 11header("Content-type: text/html; charset=utf-8"); # このコードはコンテンツはhtmlで文字コードはutf-8であるという意味。通常はプログラムでわざわざ指定しなくても 12#Webサーバが勝手につけてくれますが、プログラムから指定しているのは、より明示的に文字化けや、文字コードの違いを利用したXSS攻撃等を防ぐ 13 14try 15{ 16 17$pro_name=$_POST['name']; 18$pro_attribute=$_POST['attribute']; 19$pro_type=$_POST['type']; 20$pro_number=$_POST['number']; 21 22$pro_name=htmlspecialchars($pro_name,ENT_QUOTES,'UTF-8'); 23$pro_attribute=htmlspecialchars($pro_attribute,ENT_QUOTES,'UTF-8'); 24$pro_type=htmlspecialchars($pro_type,ENT_QUOTES,'UTF-8'); 25$pro_number=htmlspecialchars($pro_number,ENT_QUOTES,'UTF-8'); 26 27if($pro_name=='' && $pro_attribute=='' && $pro_type=='' && preg_match('/\A[0-9]+\z/',$pro_number)==0 ) 28{ 29 print("検索項目が全て空白です。値を入力してください。"); 30 print '<form>'; 31 print '<input type="button" onclick="history.back()" value="戻る">'; 32 print '</form>'; 33 exit(); 34} 35else 36{ 37 print 'カード一覧<br /><br />'; 38} 39 40$sql_part_head="SELECT code,name,attribute,type,number FROM mst_product"; 41 42$first_query = true; 43 44if(isset($_POST['name'])==true) 45{ 46 $sql_part_A = "WHERE name LIKE '%$pro_name%'"; 47 $first_query=false; 48} 49if(isset($_POST['attribute'])==true) { 50 if($first_query=false){ 51 $sql_part_B = "WHERE attribute LIKE '%$pro_attribute%'"; 52 } 53 else{ 54 $sql_part_B="attribute LIKE '%$pro_attribute%'"; 55 } 56} 57if(isset($_POST['type'])==true) { 58 if($first_query=false){ 59 $sql_part_B = "WHERE type LIKE '%$pro_type%'"; 60 } 61 else{ 62 $sql_part_B="type LIKE '%$pro_type%'"; 63 } 64} 65 66if(isset($_POST['number'])==true) { 67 if($first_query=false){ 68 $sql_part_B = "WHERE number LIKE '%$pro_number%'"; 69 } 70 else{ 71 $sql_part_B="number LIKE '%$pro_number%'"; 72 } 73} 74 75$dsn='mysql:dbname=yugioh;host=localhost;charset=utf8'; 76$user='root'; 77$password=''; 78$dbh=new PDO($dsn,$user,$password); 79$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 80 81$sql="SELECT code,name,attribute,type,number FROM mst_product '$sql_part_A'AND'$sql_part_B'AND'$sql_part_C'AND'$sql_part_D'"; 82$stmt=$dbh->prepare($sql); 83$stmt->execute(); 84 85$dbh=null; 86 87print '<form method="post" action="pro_branch.php">'; 88while(true) 89{ 90 $rec=$stmt->fetch(PDO::FETCH_ASSOC); 91 if($rec==false) 92 { 93 break; 94 } 95 print '<input type="radio" name="procode" value="'.$rec['code']. '">'; 96 print $rec['name'].' 種族:'; 97 print $rec['attribute'].' 属性'; 98 print $rec['type'].' 枚数:'; 99 print $rec['number'].'枚'; 100 print '<br />'; 101} 102 103/* if(isset($_POST['name'])==true || isset($_POST['attribute'])==true || isset($_POST['type'])==true || isset($_POST['number'])==true) #もし検索ボックスのどれかに値が入っていたら 104{ */ 105 106/* if(isset($_POST['name'])==true && $pro_attribute=='' && $pro_type=='' && $pro_number=='') */ 107/* if(isset($_POST['name'])==true ) 108{ 109 110$dsn='mysql:dbname=yugioh;host=localhost;charset=utf8'; 111$user='root'; 112$password=''; 113$dbh=new PDO($dsn,$user,$password); 114$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 115 116$sql="SELECT code,name,attribute,type,number FROM mst_product WHERE name LIKE '%$pro_name%'"; 117$stmt=$dbh->prepare($sql); 118$stmt->execute(); 119 120$dbh=null; 121 122 123print '<form method="post" action="pro_branch.php">'; 124while(true) 125{ 126 $rec=$stmt->fetch(PDO::FETCH_ASSOC); 127 if($rec==false) 128 { 129 break; 130 } 131 print '<input type="radio" name="procode" value="'.$rec['code']. '">'; 132 print $rec['name'].' 種族:'; 133 print $rec['attribute'].' 属性'; 134 print $rec['type'].' 枚数:'; 135 print $rec['number'].'枚'; 136 print '<br />'; 137} 138 139} */ 140 141/* } */ 142 143/* if(isset($_POST['name'])==true && isset($_POST['attribute'])==true && $pro_type=='' && $pro_number=='') 144{ 145 $dsn='mysql:dbname=yugioh;host=localhost;charset=utf8'; 146$user='root'; 147$password=''; 148$dbh=new PDO($dsn,$user,$password); 149$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); 150 151$sql="SELECT code,name,attribute,type,number FROM mst_product WHERE name LIKE '%$pro_name%','%pro_attribute'"; 152$stmt=$dbh->prepare($sql); 153$stmt->execute(); 154 155$dbh=null; 156 157 158print '<form method="post" action="pro_branch.php">'; 159while(true) 160{ 161 $rec=$stmt->fetch(PDO::FETCH_ASSOC); 162 if($rec==false) 163 { 164 break; 165 } 166 print '<input type="radio" name="procode" value="'.$rec['code']. '">'; 167 print $rec['name'].' 種族:'; 168 print $rec['attribute'].' 属性'; 169 print $rec['type'].' 枚数:'; 170 print $rec['number'].'枚'; 171 print '<br />'; 172} 173 174} */ 175 176 177} 178catch(PDOException $e) 179{ 180 echo "失敗:" . $e->getMessage() . "\n"; 181 exit(); 182} 183 184?> 185 186</body> 187</html>

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

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

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

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

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

yambejp

2021/04/30 00:22

もし質問者さんが初心者ならエラーがおきない最小単位を実装して徐々に 機能を付与していくことをおすすめします。
guest

回答1

0

ベストアンサー

そもそもこれはSQL文として正しいのでしょうか?

Syntax エラーは構文エラーで正しくない。正しくないからエラーが出ています。

ひとまずいきなりPHPから実行するのではなく、DBに対して直接実行して想定のデータを得られるSQLを組んで想定の結果を得られてからPHPでそのSQLになるように組み立ててください。

直接実行して想定の結果が得られなければ、PHPから実行しても想定の結果は得られません。

SQLインジェクションの脆弱性があったり、画面に出力しない項目に対してHTMLエスケープ対応していたり、実装として非常にまずいところは沢山ありますが、1つずつやっていくと良いです。


直接的なヒントとしては
=は代入
=====は比較

ifには「式」を入れますが代入も「式」であるためエラーになりません。
代入結果がfalseになることってないので、必ず通ります。

また、代入はつまるところ上書きなので、別の値が入っててもなくなります。
文字列演算子あたりも確認してください。

投稿2021/04/29 08:05

編集2021/04/29 08:12
m.ts10806

総合スコア80850

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

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

m.ts10806

2021/04/29 08:05

> $pro_name まさかまた「気づけばプロ並み」か・・?
asianLad

2021/04/29 09:57

ご回答ありがとうございます。はい、「気づけばプロ並み」を元にしてXAMPPで書いていおります。 初心者ですのでひとまずセキュリティは度外視してコードが動くかどうか試しております。
asianLad

2021/04/29 09:59

iseetはtrueで評価して判定する認識なので「==」を使うかと思ったのですがそこが間違っていますでしょうか?初心者で至らないことも多いですがよろしくお願いします。
m.ts10806

2021/04/29 10:01

if($first_query=false){ ↑比較?
m.ts10806

2021/04/29 10:02

>「気づけばプロ並み」を元にして タイトルは単なる煽り文句で入門書としても使えないと評判です(特に脆弱性を作りこむような実装はプロとしてはあり得ない)
asianLad

2021/04/29 13:39

確かにおっしゃる通りかもしれませんが、だからと言って通常なら今から教材を変えたりも簡単にできないですしプロトしての仕事を目指している段階でもなく初心者としてプログラミングを学ぼうとしているだけなので批判的な意見ではなく、もっと今ある課題に対しての直接的なアドバイスを指摘していただけたら嬉しかったです。
m.ts10806

2021/04/29 13:47 編集

「プログラミングを学ぼうとしている段階でも向かない」とも言っておきます。間違った知識を最初に身に着けてしまうとその後間違ったまま進みますし、他の回答者でも同じ指摘をされ続けます。 初心者であればPHPマニュアルを活用できるようになること、デバッグできるようになること を最優先課題とすべきと思います。 PHPマニュアルはインターネット繋がれば参照できるので無料ですし、チュートリアル的な内容もあります。公式のものなので一番正しい情報が載っています。 「今ある課題に対しての直接的な」は既に最初の回答時点でしています。 「実装として非常にまずいところは沢山ありますが、1つずつやっていくと良いです。」というフォローも入れています。 「今やろうとしていることがとりあえずできればいい」とは思う人は回答者やってないと思うので、「今後に向けたヒント」として実装部分や書籍に対する指摘も入れています。あくまで補足として。
asianLad

2021/04/30 14:25

ありがとうございます。 とりあえずこんな感じでなんとか動くところまではかけました。 これからレコードがない場合の処理なども追加していく予定です。 ``` try { $pro_name=$_POST['name']; $pro_attribute=$_POST['attribute']; $pro_type=$_POST['type']; $pro_number=$_POST['number']; $pro_name=htmlspecialchars($pro_name,ENT_QUOTES,'UTF-8'); $pro_attribute=htmlspecialchars($pro_attribute,ENT_QUOTES,'UTF-8'); $pro_type=htmlspecialchars($pro_type,ENT_QUOTES,'UTF-8'); $pro_number=htmlspecialchars($pro_number,ENT_QUOTES,'UTF-8'); if($pro_name=='' && $pro_attribute=='' && $pro_type=='' && preg_match('/\A[0-9]+\z/',$pro_number)==0 ) { print("検索項目が全て空白です。値を入力してください。"); print '<form>'; print '<input type="button" onclick="history.back()" value="戻る">'; print '</form>'; exit(); } /* else { print 'カード一覧<br /><br />'; } */ $sql_part_head="SELECT code,name,attribute,type,number FROM mst_product"; $first_query = true; if(isset($_POST['name'])==true) { $sql_part_A = "WHERE name LIKE '%$pro_name%'"; $first_query=false; } else{ if(isset($_POST['attribute'])==true) { if($first_query==true){ $sql_part_B = "WHERE attribute LIKE '%$pro_attribute%'"; } else{ $sql_part_B="attribute LIKE '%$pro_attribute%'"; } } if(isset($_POST['type'])==true) { if($first_query==true){ $sql_part_C = "WHERE type LIKE '%$pro_type%'"; } else{ $sql_part_C="type LIKE '%$pro_type%'"; } } if(isset($_POST['number'])==true) { if($first_query==true){ $sql_part_D = "WHERE number LIKE '%$pro_number%'"; } else{ $sql_part_D="number LIKE '%$pro_number%'"; } } } $dsn='mysql:dbname=yugioh;host=localhost;charset=utf8'; $user='root'; $password=''; $dbh=new PDO($dsn,$user,$password); $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); /* $sql="SELECT code,name,attribute,type,number FROM mst_product '$sql_part_A'and'$sql_part_B'and'$sql_part_C'and'$sql_part_D'"; */ $sql="SELECT code,name,attribute,type,number FROM mst_product WHERE name LIKE '%$pro_name%' AND attribute LIKE '%$pro_attribute%' AND type LIKE '%$pro_type%' AND number LIKE '%$pro_number%'"; $stmt=$dbh->prepare($sql); $stmt->execute(); $dbh=null; print '<form method="post" action="pro_branch.php">'; print 'カード一覧<br /><br />'; while(true) { $rec=$stmt->fetch(PDO::FETCH_ASSOC); if($rec==false) { break; } /* print '<input type="radio" name="procode" value="'.$rec['code']. '">'; */ print $rec['name'].' 種族:'; print $rec['attribute'].' 属性'; print $rec['type'].' 枚数:'; print $rec['number'].'枚'; print '<br />'; } } catch(PDOException $e) { echo "失敗:" . $e->getMessage() . "\n"; exit(); } ```
退会済みユーザー

退会済みユーザー

2021/04/30 21:02

気づけばプロ並みPHP は副読本を読み、アンチパターンを理解してからが本番です! 気づけばプロ並みPHP 副読本:お助け電子BOOKへの寄稿の顛末 https://blog.tokumaru.org/2014/10/php-book.html まぁ、古い本なのでさっさと見切りをつけた方がいいのは確かですけど、プログラミング学習時にアンチパターンを大量に理解できることはまれなので、一度読んでみると良いです。
m.ts10806

2021/04/30 22:32

te2jiさんそれほとんど皮肉。。。 初心者だと「これが真だ」と思ってしまうのでよろしくないです
退会済みユーザー

退会済みユーザー

2021/04/30 22:59

あーちょっと誤解を与えたかも^^; > 一度読んでみると良いです。 「副読本を」一度読んでみると良いです。だね。 なぜか、ID と PASS が公開されているので非購入者も読むことが出来そうです。 目次を見ても、問題個所のほとんどはケアされてます。 ただ、やっぱり古いんだよなぁ。。。
m.ts10806

2021/05/01 09:44

中身もそうですが、情報の鮮度は尚のこと重要ですね。 日進月歩の世界において古いとそれだけ信用度も下がります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問