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

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

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

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Q&A

解決済

3回答

4305閲覧

データベースへのデータの追加でエラーが出ます。

Yuu412

総合スコア37

PHP

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

0グッド

0クリップ

投稿2020/05/16 03:30

データベースにデータを追加する際に以下のようなエラーがでます。

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`inventory`.`goods`, CONSTRAINT `brand_id` FOREIGN KEY (`brand`) REFERENCES `brand` (`id`))

実現したいこととしては、「index.php」で入力したデータを、「insert.php」によってデータベース(inventry)に追加するというプログラムを書いています。

データベースの構造は以下のようになっています。
他に必要な情報があれば教えてください。

イメージ説明

ソースコードは以下です。

index.php

1<?php 2 require_once("util.php"); 3 4 $user = 'inventoryuser'; 5 $password = 'pw4inventoryuser'; 6 7 //利用するデータベース 8 $dbName = 'inventory'; 9 10 //MySQLサーバー 11 $host = 'localhost:3306'; 12 13 //MySQLのDSN文字列 14 $dsn = "mysql:host={$host};dbname={$dbName};charset=utf8"; 15?> 16 17 <?php 18 //MySQLデータベースに接続する 19 try{ 20 $pdo = new PDO($dsn, $user, $password); 21 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 22 23 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 24 echo "データベース{$dbName}に接続しました。<br>"; 25 26 27 $sql = "SELECT id, name FROM brand"; 28 29 //プリペアードステートメントを作る 30 $stm = $pdo->prepare($sql); 31 32 //SQL文を実行する 33 $stm->execute(); 34 35 //結果の取得(連想配列で受け取る) 36 $brand = $stm->fetchAll(PDO::FETCH_ASSOC); 37 }catch (Exception $e) { 38 echo '<span class="error">エラーがありました。</span><br>'; 39 echo $e -> getMessage(); 40 exit(); 41 } 42 ?> 43 44 <!DOCTYPE html> 45 <html lang="en" dir="ltr"> 46 <head> 47 <meta charset="utf-8"> 48 <title>データベーステスト</title> 49 </head> 50 <body> 51 <form method="POST" action="insert.php"> 52 <ul> 53 <li> 54 <label>情報を追加します<br> 55 <span>商品ID : </span> 56 <input type="text" name="id" placeholder="商品ID"><br> 57 <span>年齢を入力してください:</span> 58 <input type="text" name="name" placeholder="商品名"><br> 59 <span>性別を入力してください:</span> 60 <input type="text" name="size" placeholder="(未入力でもOK)"><br> 61 </label> 62 </li> 63 <li> 64 <select name="brand"> 65 <?php 66 foreach($brand as $row){ 67 echo '<option value=">', $row["id"], '">', $row["name"], "</option>"; 68 } 69 ?> 70 </select> 71 </li> 72 <li> 73 <label>個数: 74 <input type="number" name="quantity" placeholder="半角数字"> 75 </li> 76 <li><input type="submit" value="追加する"></li> 77 </ul> 78 </form> 79 </body> 80</html> 81

insert.php

1 2<?php 3require_once("util.php"); 4$gobackURL = "index.php"; 5 6$errors= []; 7if(!isset($_POST["id"])||($_POST["id"]==="")){ 8 $errors[] = "商品IDが空です"; 9} 10 11if(!isset($_POST["name"])||($_POST["name"]==="")){ 12 $errors[]="商品名が空です。"; 13} 14if(!isset($_POST["brand"])||($_POST["brand"]==="")){ 15 $errors[] = "ブランドが空です。"; 16} 17if(!isset($_POST["quantity"])||($_POST["quantity"]==="")){ 18 $errors[] = "個数が整数値ではありません。"; 19} 20 21if(count($errors)>0){ 22 echo '<ol class="error">'; 23 foreach($errors as $value){ 24 echo "<li>", $value, "</li>"; 25 } 26 echo "</ol>"; 27 echo "<hr>"; 28 exit(); 29} 30 31$user = 'inventoryuser'; 32$password = 'pw4inventoryuser'; 33 34//利用するデータベース 35$dbName = 'inventory'; 36 37//MySQLサーバー 38 $host = 'localhost:3306'; 39 40 //MySQLのDSN文字列 41 $dsn = "mysql:host={$host};dbname={$dbName};charset=utf8"; 42?> 43 44<!DOCTYPE html> 45<html lang="en" dir="ltr"> 46 <head> 47 <meta charset="utf-8"> 48 <title>データベーステスト</title> 49 </head> 50 <body> 51 <?php 52 //MySQLデータベースに接続する 53 54 try{ 55 $pdo = new PDO($dsn, $user, $password); 56 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 57 58 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 59 echo "データベース{$dbName}に接続しました。<br>"; 60 }catch (Exception $e) { 61 echo '<span class="error">エラーがありました。</span><br>'; 62 echo $e -> getMessage(); 63 exit(); 64 } 65 66 try{ 67 $pdo->beginTransaction(); 68 $sql1 = "INSERT INTO goods (id, name, size, brand) 69 VALUES (:id, :name, :size, :brand)"; 70 $sql2 = "INSERT INTO stock (goods_id, quantity) 71 VALUES (:goods_id, :quantity)"; 72 73 //プリペアードステートメントを作る 74 $stm1 = $pdo->prepare($sql1); 75 $stm2 = $pdo->prepare($sql2); 76 77 $stm1 -> bindValue(':id', $_POST["id"], PDO::PARAM_STR); 78 $stm1 -> bindValue(':name', $_POST["name"], PDO::PARAM_STR); 79 $stm1 -> bindValue(':size', $_POST["size"], PDO::PARAM_STR); 80 $stm1 -> bindValue(':brand', $_POST["brand"], PDO::PARAM_STR); 81 82 $stm2 -> bindValue(':goods_id', $_POST["id"], PDO::PARAM_STR); 83 $stm2 -> bindValue(':quantity', $_POST["quantity"], PDO::PARAM_INT); 84 //SQL文を実行する 85 $stm1->execute(); 86 $stm2->execute(); 87 88 $pdo->commit(); 89 90 echo "商品データ/在庫データを追加しました。"; 91 }catch (Exception $e) { 92 $pdo-> rollBack(); 93 echo '<span class="error">登録エラーがありました。</span><br>'; 94 echo $e -> getMessage(); 95 exit(); 96 } 97 ?> 98 99 <hr> 100 <p><a href="<?php echo $gobackURL;?>">戻る</a></p> 101 </body> 102</html> 103

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

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

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

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

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

snogot

2020/05/16 03:36

SQLを単体で実行した場合はエラーなく追加できますか?
guest

回答3

0

echo '<option value=">', $row["id"], '">', $row["name"], "</option>";

これだと正しくbrandのIDだけ入らないのでは。「10」ってあったら>10ってなりますよ。
生成されたHTMLを確認してください。

あとDBから取ってきた情報でもHTMLエスケープはしてください。

あとはコードの流れですが、
やはり[prepare->bindValue->execute]は一つの流れとして1つずつ完結すべきだと思います。
1とか2とかマジックナンバーつけるのもよろしくありません。
コードの可読性が非常に悪いです。

※あと別途指摘していますが、インデントがめちゃくちゃ。コーディングはIDE使ってコードフォーマットや構文チェックは実行前に済ませましょう。

投稿2020/05/16 05:56

編集2020/05/16 05:59
m.ts10806

総合スコア80850

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

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

0

ベストアンサー

(`inventory`.`goods`, CONSTRAINT `brand_id` FOREIGN KEY (`brand`) REFERENCES `brand` (`id`))

と書いてあるので先に brand と goods に insert しないといけないと思います。

投稿2020/05/16 03:36

Yasumichi

総合スコア1773

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

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

Yuu412

2020/05/16 05:39

理解が浅くて大変申し訳ないのですが、FOREIGN KEYとあるので、外部キー制約が問題かなと思っております。 私のコードでは、まず、 $sql1 = "INSERT INTO goods (id, name, size, brand) VALUES (:id, :name, :size, :brand)"; で、goodsにid, name, size, brandを登録し、(実際に登録するのは$stm1->execute();だと思いますが、) $sql2 = "INSERT INTO stock (goods_id, quantity) VALUES (:goods_id, :quantity)"; で、stockにgoods_idと、quantityを登録するというイメージです。 そのため、先に親データである、goodsにデータを登録しているので、外部キー制約ではじかれている理由がわかりません。 Yasumichiさんがおっしゃられていたことと関係ないのであればすみませんが、教えていただいてもいいでしょうか。
Yasumichi

2020/05/16 05:45

外部キー制約が原因なのは合ってると思います。 こちらもちょっと関係性を誤解しているかもしれません。
Yasumichi

2020/05/16 05:52

私の理解としては、goods の brand 列について、brand の id への外部参照制約があるように見受けられたのですが、違っていますか?
m.ts10806

2020/05/16 05:55

brand テーブルのデータと$_POSTの値次第だと思います。 barndテーブルにないデータを入れようとしているなら当該エラーにはなります。 ただしそもそもコードインデントがグチャグチャすぎて見づらい。 1ページで完結するならtry-catch何個も書く必要ないですし、スコープ的にPDO書く位置はよろしくない。 PHP以外だとビルド通らないはず。
m.ts10806

2020/05/16 05:57

そして原因に気づいたので回答してみました。
guest

0

外部キー制約の理解が曖昧であったため、MySQLの方で外部キー制約の設定方法を間違えていました。

インデントについて指摘していただいた点も以後は気をつけようと思います。

投稿2020/05/16 06:04

Yuu412

総合スコア37

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

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

m.ts10806

2020/05/16 06:06

私のほうで回答してるんですが、 > <option value=">', $row["id"], '"> このままで動くんですか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問