質問: ### 前提・実現したいこと PHPを用いたアンケートシステムを作っています。 phpMyAdminを用いてmysqlにデータベースを作成し、アンケートの結果を受け取ろうとしたところ、「返り値が空でした (行数 0)」となってしまい受け取ることができません。 ### 発生している問題・エラーメッセージ ``` 返り値が空でした (行数 0) SELECT * FROM `num_of_shots` ``` ### 該当のソースコード ``` ・HTML部分 デジカメアンケート データベースの扱い(回答確認) デジカメに関するアンケート 性別: 男 女 年代: 10代 20代 30代 40代 50代 60代 70歳以上 職業: 学生 会社員 公務員 自営業 自由業 パート・アルバイト その他 カメラの種類 一眼レフ ミラーレンズ コンパクト 携帯・スマホ その他 一週間の撮影枚数: およそコマ程度 ボタンを押して内容をご確認ください。 ・PHPデータ受け取り部分 デジカメアンケート データベースの扱い(回答確認) デジカメに関するアンケート データが未入力です。入力画面に戻ってください。"; }else{ $gender=$_POST['gender']; $age=$_POST['age']; $job=$_POST['job']; $kind=$_POST['kind']; $shots=$_POST['shots']; echo'ご回答内容'; echo'性別:'.$gender.''; echo'年代:'.$age.''; echo '職業 : '.$job.''; echo 'カメラ種類 : '. $kind.''; echo '撮影枚数 : '.$shots. 'コマ程度'; echo ''; echo'' ; echo''; echo''; echo''; echo''; echo''; echo'上記の内容でよろしければ、[書込]を押してください。'; echo ''; echo ' '; echo ''; } echo ''; echo ''; echo ''; ?> ・PHPデータ書き込み部分 example10-2 データベースの扱い(書き込み) デジカメに関するアンケート '; $sql='INSERT INTO num_of_shots(性別,年代,職業,種類,撮影枚数) VALUES("'.$gender.'","'.$age.'","' .$job.'","'.$kind.'",'.$shots.');'; $stmt=$dbh->prepare($sql); $stmt->execute(); }catch(PDOException $e){ echo '障害によりご迷惑をおかけしています。'; echo 'エラーの内容 : '. mb_convert_encoding($e->getMessage(), "UTF-8", "SJIS"); echo $e->getCode(); } $dbh=null; ?> ``` ``` HTML、PHP ``` ### 試したこと Chromeの検索履歴やキャッシュの消去を行いましたが改善しませんでした。 ![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/ce2ee31895a0d4955b05d0a0def43663.png) ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。
回答: `$dsn='mysql:host=localhost;bdname=digicam_q;charset=utf8';` ↓ `$dsn='mysql:host=localhost;dbname=digicam_q;charset=utf8';` とか? new PDO()するあたりでtry~catchせず、 データベースに接続が成功しているか検証せずに処理を進めていて、 INSERT INTO文だけtry~catchで囲むのは エラー対策が甘いと言わざるを得ません。 今一度ご確認ください。 ``` $sql='INSERT INTO num_of_shots(性別,年代,職業,種類,撮影枚数) VALUES("'.$gender.'","'.$age.'","' .$job.'","'.$kind.'",'.$shots.');'; ``` これ、SQLインジェクション攻撃される、やってはいけないやり方になります。 SQL文をプリペアドステートメントで与えるようにします。 ``` $sql = <<prepare($sql); $stmt->bindValue(':gender', $gender, PDO::PARAM_STR); $stmt->bindValue(':age', $age, PDO::PARAM_STR); $stmt->bindValue(':job', $job, PDO::PARAM_STR); $stmt->bindValue(':kind', $kind, PDO::PARAM_STR); $stmt->bindValue(':shots', $shots, PDO::PARAM_STR); $stmt->execute(); ``` などと机上のコードですが直してみました。 もちろん、テーブルの構造によっては、文字列でなく数値データであれば `PDO::PARAM_STR`でなく`PDO::PARAM_INT`を使ったりします。 参考: PHPでデータベースに接続するときのまとめ - Qiita あと、 ``` if(($_POST['shots']=='')||(!isset($_POST['shots']))){ echo "データが未入力です。入力画面に戻ってください。"; }else{ ``` の箇所もちょっと気になる。 ``` if ( (!isset($_POST['shots'])) || ($_POST['shots']=='') ) { echo "データが未入力です。入力画面に戻ってください。"; } else { ``` isset()での評価を前に持ってくれば、 もしもPOST送信データにshotsが含まれていないときに Notice: Undefined index のエラーを回避できそう。 他のフォーム入力データも、データの存在チェックをしっかり厳しく行ってください。 面倒なら、 filter_input を駆使したほうがいいです。