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

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

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

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

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

Q&A

解決済

3回答

3071閲覧

PHPMyAdminから取得してきた値が変わらない

newyee

総合スコア213

phpMyAdmin

phpMyAdminはオープンソースで、PHPで書かれたウェブベースのMySQL管理ツールのことです。

PHP

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

0グッド

0クリップ

投稿2017/08/25 03:56

編集2017/08/25 04:38

PHPにて、PHPMyAdminから取得してきた値をラジオボタンで選択し、送信したのですが毎回同じ値が送られてきてしまいます。
以下が僕が作成したコードになります。

php

1<?php 2date_default_timezone_set('Asia/Tokyo'); 3const HOST = ''; 4const DB_NAME = ''; 5const USER_NAME = ''; 6const PASSWORD = ''; 7$err_msg = array(); 8$change = 0; 9$drink_name = ''; 10$date = date('Y/m/d H:i:s'); 11$drink_info_list = array(); 12 13if(($link = mysqli_connect(HOST,USER_NAME,PASSWORD,DB_NAME)) !== FALSE){ 14 mysqli_set_charset($link,'UTF8'); 15 16 17 if($_SERVER['REQUEST_METHOD'] === 'POST') { 18 $stock_numbers = (int)$_POST['stock_numbers']; 19 $drink_id = (int)$_POST['drink_id']; 20 $selected_drink = $_POST['selected_drink']; 21 $amount_money = trim(mb_convert_kana($_POST['amount_money'],"s",'UTF-8')); 22 $amount_money_length = mb_strlen($amount_money, "UTF-8"); 23 $amount_money_width = mb_strwidth($amount_money, "UTF-8");//不要では 24 25 //入力値チェック 26 if($selected_drink === NULL){ 27 $err_msg[] = 'ドリンクを指定して下さい'; 28 } 29 30 if(empty($amount_money) === TRUE){ 31 $err_msg[] = '金額を入力してください'; 32 } 33 if($amount_money_length === $amount_money_width){ 34 if(empty($amount_money) === FALSE){ 35 if(ctype_digit($amount_money) === FALSE){ //ctype_digit:string型以外はfalseになる。 36 $err_msg[] = '金額は整数で入力してください'; 37 } 38 } 39 }else{ 40 $err_msg[] = '金額は半角で入力して下さい'; 41 42 43 } 44 45 46 47 48 49 $amount_money = (int)$amount_money; 50 51 52 //var_dump($amount_money);exit(); 53 54 55 56 //エラーメッセージが空だった場合 57 if (count($err_msg) === 0){ 58 $sql = 'SELECT drink_name,price FROM drink_info_table WHERE drink_id = ' . $drink_id; 59 60 if($result = mysqli_query($link,$sql)){ 61 while($row = mysqli_fetch_assoc($result)){ //while文について質問。 62 63 $price = htmlspecialchars($row['price'],ENT_QUOTES, 'UTF-8'); 64 $drink_name = htmlspecialchars($row['drink_name'],ENT_QUOTES, 'UTF-8'); 65 var_dump($drink_id);exit(); 66 } 67 }else{ 68 $err_msg[] = 'drink_info_table:SELECTエラー:'.$sql; 69 } 70 71 72 if($amount_money < $price){ 73 $err_msg[] = '金額が足りません'; 74 } 75 if($amount_money > $price){ 76 $change = $amount_money - $price; 77 } 78 79 } 80 //エラーがあってもUPDATEするの?? 81 if (count($err_msg) === 0){ 82 $sql = 'UPDATE drink_stock_table SET stock_number = ' . $stock_numbers . '- 1 WHERE drink_id = ' . $drink_id; 83 if(mysqli_query($link,$sql) === FALSE){ 84 $err_msg[] = 'drink_stock_table: UPDATEエラー' . $sql; 85 } 86 $sql = 'INSERT INTO drink_history_table(drink_id,bought_date) VALUES (' . $drink_id . ',\''. $date .'\')'; 87 if(mysqli_query($link,$sql) === FALSE){ 88 $err_msg[] = 'drink_history_table: insertエラー' . $sql; 89 } 90 } 91 92 } 93}else{ 94 $err_msg[] = 'DB接続失敗'; 95} 96 97 98 99?> 100 101 102<!DOCTYPE html> 103<html lang="ja"> 104<head> 105 <meta charset="UTF-8"> 106 <title></title> 107</head> 108<body> 109 <h1>自動販売機結果</h1> 110 <?php foreach($err_msg as $value){ ?> 111 <p><?php echo $value; ?></p> 112 <?php } ?> 113 <?php if(count($err_msg) === 0){?> 114 <img src="img/<?php echo $drink_id ;?>.pic"> 115 <p>がしゃん!【<?php echo $drink_name; ?>】が買えました! </p> 116 <?php } ?> 117 <?php if($change >= 1){ ?> 118 <p>おつりは【<?php echo $change; ?>円】です</p> 119 <?php } ?> 120 <footer> 121 <a href="index.php">戻る</a> 122 </footer> 123</body> 124</html>

上記のコードは選択された値の送られ先となります。(result.php)
下記が値を選択し、送る側のコードとなります。(index.php)

php

1<?php 2const HOST = ''; 3const DB_NAME = ''; 4const USER_NAME = ''; 5const PASSWORD = ''; 6$drink_info_list = array(); 7 8//DB接続 9if(($link = mysqli_connect(HOST,USER_NAME,PASSWORD,DB_NAME)) !== FALSE){ 10 mysqli_set_charset($link,'UTF8'); 11 // sql where にて 以下の条件を追加すること。 12 // 1.ステータスが公開になっているもののみを表示。 13 // 2.在庫数が1以上の商品のみ。 14 $sql = 'SELECT drink_info_table.drink_id,drink_name,price,status,stock_number 15 FROM drink_info_table 16 JOIN drink_stock_table 17 ON drink_info_table.drink_id = drink_stock_table.drink_id 18 WHERE status = 1 AND stock_number >= 1;'; 19 20 21 if($result = mysqli_query($link,$sql)){ 22 $i = 0; 23 while($row = mysqli_fetch_assoc($result)){ 24 $drink_info_list[$i]['drink_id'] = htmlspecialchars($row['drink_id'],ENT_QUOTES, 'UTF-8'); 25 $drink_info_list[$i]['drink_name'] = htmlspecialchars($row['drink_name'],ENT_QUOTES, 'UTF-8'); 26 $drink_info_list[$i]['price'] = htmlspecialchars($row['price'],ENT_QUOTES, 'UTF-8'); 27 $drink_info_list[$i]['status'] = htmlspecialchars($row['status'],ENT_QUOTES, 'UTF-8'); 28 $drink_info_list[$i]['stock_number'] = htmlspecialchars($row['stock_number'],ENT_QUOTES, 'UTF-8'); 29 30 $i++; 31 } 32 33 // var_dump($drink_info_list);exit(); 34 } 35 36 37 38} 39 40?> 41 42 43<!DOCTYPE html> 44<html lang="ja"> 45<head> 46 <meta charset="UTF-8"> 47 <title></title> 48</head> 49<body> 50 <h1>自動販売機</h1> 51 52 <form action="result.php" method="post"> 53 <div>金額<input type="text" name="amount_money"></div> 54 <!--画像を表示すること--> 55 <?php foreach($drink_info_list as $values){ ?> 56 <img src="img/<?php echo $values['drink_id'] ;?>.pic"> 57 <?php echo $values['drink_name']; ?> 58 <?php echo $values['price']; ?> 59 60 <?php if((int)$values['stock_number'] === 0){ ?> 61 <p>売り切れ</p> 62 <?php } else { ?> 63 <input type="radio" name="selected_drink"> 64 <?php } ?> 65 66 <?php } ?> 67 68 <p><input type="submit" value="■□■□■購入■□■□■"></p> 69 <input type="hidden" name="stock_numbers" value="<?php echo $values['stock_number']; ?>"> 70 <input type="hidden" name="drink_id" value="<?php echo $values['drink_id'];?>"> 71 72 </form> 73 74</body> 75</html>

「同じ値」ということなんですが、「result.php」の
$drink_name = htmlspecialchars($row['drink_name'],ENT_QUOTES, 'UTF-8');の下の行でvar_dumpした所,
var_dump($drink_id);exit();選択肢を変えても、毎回同じ「$drink_id」が送られてきてしまいます。
下記はindex.phpの実行画面となります。

イメージ説明
金額を入力し、どの商品を選択しても必ずコーラが購入されてしまいます。
イメージ説明
ちなみになのですが、$drink_idでvar_dumpした所を、$drink_nameにしたら文字化してしまい、判定できませんでした...
どなたか、教えて下さる方いましたらご教授願います...

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

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

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

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

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

m.ts10806

2017/08/25 04:04

概念的な問題ですがPHPMyAdminはデータベース:MySQLの情報を閲覧・編集するツールであってDBそのものではありません。
m.ts10806

2017/08/25 04:14 編集

あと、以前の質問でもコメントしましたがキャストは不要ですよ。なくてもきちんと動くはず。(逆キャストのためのコストが無駄にかかります)
m.ts10806

2017/08/25 04:56

回答したものの、そのあとに結構追記してしまったので、ご確認お願いします。
newyee

2017/08/26 09:48

回答ありがとうございます。確認致しました!
guest

回答3

0

ベストアンサー

気になるところをざっと洗い出してみました(前の質問と一部重複あります)

  • input hiddenのdrink_idはforeachの外にあるため、おそらく最後のレコードのdrink_idが入っている

→毎回同じ(最後のレコードのdrink_id)が送信される
「選択したドリンクを購入」で購入ボタン1つにしたいのであればradioのselected_drinkのvalueにdrink_idをそれぞれ入れてresult.phpで受け取る
それか本当の自販機のようにそれぞれの商品の下にボタンを置いてonclickでhiddenのdrink_idに入れてPOSTする 
stock_numbersも同様。これだと最後のレコードのdrink_idのみ更新されてしまう

  • キャストは不要(理由はコメントに書いたとおり)
  • エラーメッセージはシステム的なものとSQLも含むようですが、それを画面出力するのはセキュリティ上NG

どうしてもエラーが知りたいならブラウザから参照不可能な場所にログファイルとして出力すべき

  • 金額が足りないチェックに利用しているSQLはdrink_idをwhereにしているためwhileでループする意味がない。

fetchは「次のデータに取得ポインタを移す」なのでwhileしたところで1件しか対象がないので1周しか回らない。

  • というか金額が足らない場合は画面に購入商品情報出さないんだから、金額足らないチェックもSQLに入れたほうが良くない?
SELECT drink_name FROM drink_info_table WHERE drink_id = ' . $drink_id .' and price < '.$amount_money

で0件なら金額不足エラー、1件なら金額足りてるのでエラーなしで情報取得

  • 金額不足のチェックを}で閉じなくてもelseでつないでしまっても差し支えない

PHP

1if($amount_money < $price){ 2 $err_msg[] = '金額が足りません'; 3}else{ 4 $change = $amount_money - $price; 5}

またおつり出したいならちょっと特殊ですが、

SELECT drink_name,price,('.$amount_money.'- price) as change FROM drink_info_table WHERE drink_id = ' . $drink_id .' and price < '.$amount_money

とかで計算もSQLでしてしまえばコードがすっきりします。
※未検証なので調整してください

  • htmlspecialchars()は取得時ではなく表示時のほうがタイミングとしては望ましい
  • PDOなどを使わず生のSQLに入力値を渡すのであればsqlのエスケープは必ず行いましょう(PHPマニュアル:mysqli_real_escape_string()
  • stock_numbers更新について、前の画面からはhiddenで渡して使ってますが、更新のためだけに使ってますよね。それでしたらSQLでは「自身のカラム」が式の右辺にも使えるので、持っておくのは不要です。

sql

1UPDATE drink_stock_table SET stock_number = stock_number - 1 WHERE drink_id = ' . $drink_id;

「自身の現在の値から1を引く」っていう書き方ですね。この方が在庫の増減のさせ方としては確実です。
というのは商品選択画面のhiddenのstock_numberから引いているので、
ほぼ同時に購入処理を実行した場合に、見た目減っていない現象が起きる可能性があるからです。

余談:
むかーしの私とコードの書き方が非常に似ていたため沢山書いてしまいましたが、
いずれも大事なことと思いますので、1つ1つ対応してみてください。

投稿2017/08/25 04:33

編集2017/08/25 04:55
m.ts10806

総合スコア80850

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

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

newyee

2017/08/25 09:21

前回に引き続き大変ご丁寧なご回答ありがとうございます。 ご指摘頂いた点を一つづつ修正していきたいと思っております。 色々分からない部分も多く、お聞きしたい箇所もたくさんあるのですが、一つずつご質問させていただければと思っています。 ご指摘頂いた、ここの部分「input hiddenのdrink_idはforeachの外にあるため、おそらく最後のレコードのdrink_idが入っている」なのですが、自分なりに修正してみたのですが、上手くいきませんでした... 以下は、「index.php」の「foreach」文内の修正した箇所になります。 <form action="result.php" method="post"> <div>金額<input type="text" name="amount_money"></div> <!--画像を表示すること--> <?php foreach($drink_info_list as $values){ ?> <img src="img/<?php echo $values['drink_id'] ;?>.pic"> <?php echo $values['drink_name']; ?> <?php echo $values['price']; ?> <?php if((int)$values['stock_number'] === 0){ ?> <p>売り切れ</p> <?php } else { ?> <input type="radio" name="selected_drink" value="<?php echo $values['drink_id'];?>"> <?php } ?> <input type="hidden" name="stock_numbers" value="<?php echo $values['stock_number']; ?>"> <?php } ?> <p><input type="submit" value="■□■□■購入■□■□■"></p> </form> ラジオボタンに、value="<?php echo $values['drink_id']と、追加してみたのですが、今度はどの商品をを選択しても「コーラ」ではなく画像の紫色の飲み物(グレープ)が購入、と表示されてしまいます。それ+ドリンク名は出力されていない状況です。result.phpの $amount_money_width = mb_strwidth($amount_money, "UTF-8");の下の部分でvar_dump($drink_id);としたら、int(0)と表示されていました... なにがなんだか訳が分からない状況です... お手数かと思いますが、ご返信頂けたら幸いです...
newyee

2017/08/27 11:29

アドバイスを参考にさせて頂いた結果、エラーが解消され動作させることができました! 前回も頂いたキャストが不要というご指摘だったのですが自分としましては、 if($amount_money < $price){ $err_msg[] = '金額が足りません'; }else{ $change = $amount_money - $price; } ここの部分で、$amount_money をキャストしなかった場合、文字列と数値をif文で比較することになっ てしまうと思ったためです!
m.ts10806

2017/08/28 00:12

文字列と数値をif文で比較したところでエラーは起きません(そういうところはPHPは緩く助かる部分でもあり、場合により事故につながる部分となります) キャストは基本的に失敗がないため、どのような情報(例えばNULLとか空文字とか配列とかクラスオブジェクトとか)を入れ込んだとしても指定した型に強引に変換してしまうため、前の質問で提示した「安易にキャストするな」の記事にあるように気づけたはずのエラーに気づけなくなってしまいます。 文字列と数値を比較するのが心配であればその前の段階で数値であるというチェックを挟めば良い事です。(つまりどのようなケースにおいてもキャストは不要で、型チェックは事前にして正しい型であることを保証してから利用すべきということ。この辺りはどの言語も同じですね)
guest

0

drink_idはhiddenで受け取るのではなく、ラジオボタンに紐づけないといけないのではないでしょうか。
つまり、input type="radio"にvalueプロパティが必要かと。

PHP

1<input type="radio" name="selected_drink"> 23<input type="radio" name="drink_id" value="<?php echo $values['drink_id'];?>">

あとhiddenのdrink_idは削除してください。

投稿2017/08/25 04:33

ttyp03

総合スコア16998

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

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

0

ざっとしか見てないのですが、、、
送る側の表示の部分で

PHP

1 2 <input type="hidden" name="stock_numbers" value="<?php echo $values['stock_number']; ?>"> 3 <input type="hidden" name="drink_id" value="<?php echo $values['drink_id'];?>"> 4

上記のコードはforeach内に入れないと、駄目じゃないですか?

ソースをブラウザで見た時とかに値がちゃんとセットされてますか?

投稿2017/08/25 04:09

Z-TALBO

総合スコア525

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問