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

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

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

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

PHP

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

Q&A

解決済

3回答

566閲覧

[PHP]エラーの原因がわかりません。

newyee

総合スコア213

phpMyAdmin

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

PHP

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

0グッド

0クリップ

投稿2017/08/24 03:52

現在、PHPの勉強で自動販売機作成ツールを作成途中なのですが、エラーの原因や実行結果において上手くいかない部分があり、ご教授頂ければ幸いです...
3つのファイル(管理ページ、購入ページ、購入結果ページ)に分けて作成していまして、以下のコードは購入ページより商品が選択されて送信されてきた購入結果ページになります。

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 = ''; 9$date = date('Y/m/d H:i:s'); 10$drink_info_list = array(); 11 12if(($link = mysqli_connect(HOST,USER_NAME,PASSWORD,DB_NAME)) !== FALSE){ 13 if ($_SERVER['REQUEST_METHOD'] === 'POST') { 14 $stock_numbers = (int)$_POST['stock_numbers']; 15 $amount_money = (int)$_POST['amount_money']; 16 //入力値チェック 17 if($_POST['selected_drink'] === ''){ 18 $err_msg[] = 'ドリンクを指定して下さい'; 19 } 20 if(ctype_digit($amount_money) === FALSE){ 21 $err_msg[] = '金額は整数で入力してください'; 22 } 23 if($price > $amount_money){ 24 $err_msg[] = '金額が足りません'; 25 } 26 27 //エラーがなかった場合 28 if (count($error_msg) === 0){ 29 $drink_id = (int)$_POST['drink_id']; 30 31 $sql = 'SELECT drink_name,price FROM drink_info_table WHERE drink_id = ' . $drink_id; 32 33 if($result = mysqli_query($link,$sql)){ 34 while($row = mysqli_fetch_assoc($result)){ //while文について質問。 35 36 $price = htmlspecialchars($row['price'],ENT_QUOTES, 'UTF-8'); 37 $drink_name = htmlspecialchars($row['drink_name'],ENT_QUOTES, 'UTF-8'); 38 } 39 }else{ 40 $err_msg[] = 'drink_info_table:SELECTエラー:'.$sql; 41 } 42 43 44 45 if($amount_money > $price){ 46 $change = $amount_money - $price; 47 } 48 49 $sql = 'UPDATE drink_stock_table SET stock_number = ' . $stock_numbers - 1 . ' WHERE drink_id = ' . $drink_id; 50 if(mysqli_query($link,$query) === FALSE){ 51 $err_msg[] = 'drink_stock_table: UPDATEエラー' . $sql; 52 } 53 54 $sql = 'INSERT INTO drink_history_table(drink_id,bought_date) VALUES (' . $drink_id . ',' . $date . ');'; 55 if(mysqli_query($link,$sql) === FALSE){ 56 $err_msg[] = 'drink_history_table: insertエラー' . $sql; 57 } 58 //var_dump($stock_numbers);exit(); 59 60 61 } 62 63 } 64}else{ 65 $err_msg[] = 'DB接続失敗'; 66} 67 68 69 70?> 71 72 73<!DOCTYPE html> 74<html lang="ja"> 75<head> 76 <meta charset="UTF-8"> 77 <title></title> 78</head> 79<body> 80 <h1>自動販売機結果</h1> 81 <?php foreach($err_msg as $value){ ?> 82 <p><?php echo $value; ?></p> 83 <?php } ?> 84 85 <p><?php echo $change; ?></p> 86 <footer> 87 <a href="index.php">戻る</a> 88 </footer> 89</body> 90</html>

以下は購入ページのコードになります。
文字数制限上画像となってしまい、申し訳ないです。
イメージ説明
イメージ説明
イメージ説明
実行した結果と致しましては、以下の通りです。
イメージ説明
エラーの原因が分からないのもそうなのですが、購入結果ページにおいて、ctype_digit関数で整数でなければFALSEとしているのですが、購入ページで整数を入力しているにも関わらずエラーメッセージが表示されているのも分からないんですよね...
購入結果ページの完成形としましては、こちらの画像のようにできればと思っています。
イメージ説明

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

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

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

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

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

m.ts10806

2017/08/24 04:06

エラーの意味自体は調べて、理解はしましたか?(それがほぼ原因そのままです)
guest

回答3

0

MySQLの接続にはmysqliを利用されているようですが、
値の受け渡しにデータを直接ねじ込んでいるように見受けられます。
今回のエラーに関してはINSERTするVALUESに埋め込む日時データが
クォーテーションに囲まれていないことが一番の原因だと思います

2017/08/24 12:34:55
↓↓↓
'2017/08/24 12:34:55'

しかし、現在DBとのやり取りに直接変数を渡すような処理はお勧めできません
プレースホルダーにてprepareで処理するようにしてください

投稿2017/08/24 04:16

yambejp

総合スコア114784

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

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

newyee

2017/08/24 09:32

ご回答ありがとうございます。 他の回答者様のおかげもあり、指摘頂いた部分及び、ご質問させていただきました部分はすべて改善できました!
guest

0

UPDATEエラー

php

1// BAD 2$sql = 'UPDATE drink_stock_table SET stock_number = ' . $stock_numbers - 1 . ' WHERE drink_id = ' . $drink_id; 3 4// GOOD 5$sql = 'UPDATE drink_stock_table SET stock_number = ' . $stock_numbers . ' - 1 WHERE drink_id = ' . $drink_id;

文字列結合の中で数値演算が入ってしまっています。
- 1という部分をSQLの中に入れてしまいましょう。

INSERTエラー

php

1// BAD 2$sql = 'INSERT INTO drink_history_table(drink_id,bought_date) VALUES (' . $drink_id . ',' . $date . ');'; 3 4// GOOD 5$sql = "INSERT INTO drink_history_table(drink_id,bought_date) VALUES ($drink_id,'$date');"; 6

日付部分をシングルクォーテーションで囲みます。
文字列自体の囲みをシングルクォーテーションにすると、文字列の中のシングルクォーテーションの扱いが難しくなるので、ダブルクォーテーションで囲みます。

その他、result.phpの50行目で、mysqli_query()にSQLが渡されていないようですが、ソースコードが提示されていないようなので回答できません。

---追記
result.phpの50行目の件は勘違いでした。
他の方が書かれている通り、変数を間違えていますね。

投稿2017/08/24 04:30

編集2017/08/24 04:40
tsuemura

総合スコア663

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

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

m.ts10806

2017/08/24 04:35

質問本文に書かれていないので分かりづらいですが最初のソースがresult.phpだと思います。 50行目にちゃんと私が回答で指摘した箇所が出てきます。
tsuemura

2017/08/24 04:40

見落としておりました。ありがとうございます。
newyee

2017/08/24 09:21

大変ご丁寧なご回答ありがとうございます。 INSERTエラー、UPDATEエラーともにご指摘の通り修正しましたら改善されました! UPDATEエラーの「-1」というのをシングルクォーテーションの中にいれても計算されるのかなって思っていたのですが、実行するのはSQLなので関係ないですよね...^^; 完全に勘違いしていました...
newyee

2017/08/24 09:25

あ、INSERTエラーに関しての日付をシングルクォートで囲う部分は、「\'」で対応しました。 こちらは学習済みだったもので! ご親切にありがとうございました!
guest

0

ベストアンサー

最初のエラー(mysqli_query()のwarning)の解消についてはresult.php 50行目を下記のように修正してください。

PHP

1現在 2if(mysqli_query($link,$query) === FALSE){ 3 45 6修正後 7if(mysqli_query($link,$sql) === FALSE){

前後確認を行うとわかりますが、$queryという変数はどこにも出てきていないのにいきなり使われています。
このような現象を回避するためにはSQLを格納する変数は使いまわすのではなく、用途に合わせた名前をそれぞれつけてそれぞれ使った方が良いです。

購入結果ページにおいて、ctype_digit関数で整数でなければFALSEとしているのですが、購入ページで整数を入力しているにも関わらずエラーメッセージが表示されているのも分からないんですよね...

何を入力したかにもよります。小数点や空白が含まれていた場合などは「文字列」と解釈されるはずですし。
あくまで「すべての文字が 10 進数字の場合にTRUE」なので。

直接解決とならないかもしれませんが、強いてなら、入力チェックを行うのであれば(int)等の型変換は不要に思います。
入力チェックによって拾えるはずのエラーも拾えなくなる可能性がありますので。
参考:初心者を戒めるPHP-安易にキャストするな
PHPにおいて型キャストが役に立つ場面ってほとんどないです。
キャストするのではなく、不正な情報がきたことをプログラム側で感知して弾くことがあるべき姿です。

↑に対する追記。
自身の後学のためにも試してみました。

php

1$a = "1"; 2var_dump(ctype_digit($a)); 3//true 4$b = "2"; 5var_dump(ctype_digit((int)$b)); 6//false

やはり(int)のキャストが原因のようです。
ctype_digit()はあくまで「文字列が10 進数か判定する」ものであり、
キャストすることによって「数値型」となるので「false」と判定され、今回のプログラムでは「整数ではない」と判断されるようですね。
マニュアルにも引数の型は「string」となっているので、そもそもstring以外はfalseと判定するようですね。

追記:
提示情報から授業の課題のようなものだと推察されますので、
セキュリティ面とか開発効率面といった観点からのツッコミは控えておきます。

投稿2017/08/24 04:17

編集2017/08/24 04:50
m.ts10806

総合スコア80850

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

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

newyee

2017/08/24 09:13

大変ご丁寧なご回答ありがとうございます。 まさか$queryと入力しているとは思わず、全く気づきませんでした... 自分でやっといてなんなんですがね... アドバイス頂いた通り、用途に合わせた名前を付けるようにしていこうと思います。 ctype_digit()に関してなんですが、入力チェックを始める前はキャストをせず、入力チェックを終えた後に、キャストしたら、エラーメッセージが消えました! 変更内容は以下の通りです。 $stock_numbers = (int)$_POST['stock_numbers']; $amount_money = $_POST['amount_money']; //入力値チェック if($_POST['selected_drink'] === ''){ $err_msg[] = 'ドリンクを指定して下さい'; } if(ctype_digit($amount_money) === FALSE){ $err_msg[] = '金額は整数で入力してください'; } if($price > $amount_money){ $err_msg[] = '金額が足りません'; } $amount_money = (int)$amount_money; UPDATEエラーとINSERTエラーに関しましては、他の回答者様のご指摘の通り修正しましたら改善できました!
m.ts10806

2017/08/25 04:08 編集

入力チェックを終えた値であれば整数であることが保証されているのでキャストする意味ありませんよね。 つまり基本的にPHPの処理にキャストは不要です。 正しくチェックが行われているのでしたらキャストを全て取っ払っても問題ないはずです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問