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

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

ただいまの
回答率

91.37%

  • PHP

    15137questions

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

  • MySQL

    4379questions

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

PHP,MySQLのエラー処理がうまく出来ない

解決済

回答 1

投稿 2017/11/26 15:18 ・編集 2017/11/27 14:28

  • 評価
  • クリップ 1
  • VIEW 73

oyatsu8

score 57

現在PHPとMySQLの学習をしています。
詳細! PHP 7+MySQL 入門ノート(大重 美幸 (著))にあるトランザクション処理を参考に自分のMacのMAMP上で実行しているのですが、どうしてもわからないことがあり、質問させて頂きます。


テーブルは下記の3つです。
(1)mainテーブルを中心に、(2),(3)とリレーションしています。
フォームから入力すると、DB上に商品が増えて行きたいのですが、
うまく出来ていません。
フォームの表示、入力までは出来ているように見えるのですが、
confirm.php を見ると、

タイトルが空です。
材料が空です。

という表示が出てしまい、
データベースの方にもデータが格納されていません。

わからないことは、

  • テーブルの組合せがこれで大丈夫なのか(単純ですが間違っているのか)
  • confirm.php の、エラー処理で引っかかっているのですが、ここがおかしいのでしょうか
  // 簡単なエラー処理
  $errors = [];
  if (!isset($_POST["id"])||($_POST["id"]==="")){
    $errors[] = "IDが空です。";
  }

  if (!isset($_POST["table_name"])||($_POST["table_name"]==="")){
    $errors[] = "タイトルが空です。";
  }

  if (!isset($_POST["material_name"])||($_POST["material_name"]==="")) {
    $errors[] = "材料が空です。";
  }

アドバイスを頂けたら幸いです。


(1) mainテーブル

id(主キー) id_title(外部キー) id_material(外部キー)

(2) 番号リストtable_titleテーブル

id_title(主キー) title_ja

(3) table_materialテーブル
-- あらかじめ材料は入力し、フォームから選択する

id_material(主キー) material_name

コードは下記が

  • form.php
<?php
require_once("util.php");
$gobackURL = "insertform.html";

// データベースユーザ
$user = '----';
$password = '----';
// 利用するデータベース
$dbName = '----';
// MySQLサーバ
$host = '----';
// MySQLのDSN文字列
$dsn = "mysql:host={$host};dbname={$dbName};charset=utf8";
//MySQLデータベースに接続する
try {
  $pdo = new PDO($dsn, $user, $password);
  // プリペアドステートメントのエミュレーションを無効にする
  $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
  // 例外がスローされる設定にする
  $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

  // ブランドテーブルから材料IDと材料名を取り出す
  $sql = "SELECT id_material, material_name FROM table_material";
  // プリペアドステートメントを作る
  $stm = $pdo->prepare($sql);
  // SQLクエリを実行する
  $stm->execute();
  // 結果の取得(連想配列で受け取る)
  $table_material = $stm->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
  $err =  '<span class="error">エラーがありました。</span><br>';
  $err .= $e->getMessage();
  exit($err);
}
?>

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>レコード追加</title>
</head>
<body>
<div>
  <!-- 入力フォームを作る -->
  <form method="POST" action="confirm.php">
    <ul>
      <li>
        <label>ID:
        <input type="text" name="id" placeholder="ID">
        </label>
      </li>
      <li>
        <label>商品名:
        <input type="text" name="table_name" placeholder="商品名">
        </label>
      </li>
      <li>材料:
        <select name="table_material">
          <?php
          // 材料は材料テーブルに登録してあるものから選ぶ
          foreach ($table_material as $row){
            echo '<option value="', $row["id_material"], '">', $row["material_name"], "</option>";
          }
          ?>
        </select>
      </li>
<!--       <li>
        <label>個数:
        <input type="number" name="quantity" placeholder="半角数字">
      </li> -->
      <li><input type="submit" value="追加する"></li>
    </ul>
  </form>
</div>
</body>
</html>
  • confirm.php
<?php
require_once("util.php");
$gobackURL = "form.php";

// 文字エンコードの検証
if (!cken($_POST)){
  header("Location:{$gobackURL}");
  exit();
}
?>

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>レコード追加</title>
</head>
<body>
<div>

<?php
  // 簡単なエラー処理
  $errors = [];
  if (!isset($_POST["id"])||($_POST["id"]==="")){
    $errors[] = "IDが空です。";
  }
  if (!isset($_POST["table_name"])||($_POST["table_name"]==="")){
    $errors[] = "タイトルが空です。";
  }
  if (!isset($_POST["material_name"])||($_POST["material_name"]==="")) {
    $errors[] = "材料が空です。";
  }

  //エラーがあったとき
  if (count($errors)>0){
    echo '<ol class="error">';
    foreach ($errors as $value) {
      echo "<li>", $value , "</li>";
    }
    echo "</ol>";
    echo "<hr>";
    echo "<a href=", $gobackURL, ">戻る</a>";
    exit();
  }


// データベースユーザ
  $user = '----';
  $password = '----';
  // 利用するデータベース
  $dbName = '----';
  // MySQLサーバ
  $host = '----';
  // MySQLのDSN文字列
  $dsn = "mysql:host={$host};dbname={$dbName};charset=utf8";

  //MySQLデータベースに接続する
  try {
    $pdo = new PDO($dsn, $user, $password);
    // プリペアドステートメントのエミュレーションを無効にする
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    // 例外がスローされる設定にする
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  } catch (Exception $e) {
    $err =  '<span class="error">エラーがありました。</span><br>';
    $err .= $e->getMessage();
    exit($err);
  }

  try {
    // トランザクションを開始する
    $pdo->beginTransaction();
    // SQL文を作る
    $sql1 = "INSERT INTO table_material (id_material, material_name)
    VALUES (:id_material, :material_name)";

    $sql2 = "INSERT INTO table_title (id_name, name) VALUES (:id_name, :name)";
    // プリペアドステートメントを作る
    $insertGoods = $pdo->prepare($sql1);
    $insertStock = $pdo->prepare($sql2);

    // プレースホルダに値をバインドする
    $insertGoods->bindValue(':id_material', $_POST["id_material"], PDO::PARAM_STR);
    $insertGoods->bindValue(':material_name', $_POST["material_name"], PDO::PARAM_STR);

    $insertStock->bindValue(':id_name', $_POST["id_name"], PDO::PARAM_STR);
    $insertStock->bindValue(':name', $_POST["name"], PDO::PARAM_INT);

    // SQL文を実行する
    $insertGoods->execute();
    $insertStock->execute();
    // トランザクション処理を完了する
    $pdo->commit();
    // 結果報告
    echo "商品データ/在庫データを追加しました。";
  } catch (Exception $e) {
    // エラーがあったならば元の状態に戻す
    $pdo->rollBack();
    echo '<span class="error">登録エラーがありました。</span><br>';
    echo $e->getMessage();
  }
  ?>
  <hr>
  <p><a href="<?php echo $gobackURL ?>">戻る</a></p>
</div>
</body>
</html>
  • util.php
<?php
// XSS対策のためのHTMLエスケープ
function es($data, $charset='UTF-8'){
  // $dataが配列のとき
  if (is_array($data)){
    // 再帰呼び出し
    return array_map(__METHOD__, $data);
  } else {
    // HTMLエスケープを行う
    return htmlspecialchars($data, ENT_QUOTES, $charset);
  }
}

// 配列の文字エンコードのチェックを行う
function cken(array $data){
  $result = true;
  foreach ($data as $key => $value) {
    if (is_array($value)){
      // 含まれている値が配列のとき文字列に連結する
      $value = implode("", $value);
    }
    if (!mb_check_encoding($value)){
      // 文字エンコードが一致しないとき
      $result = false;
      // foreachでの走査をブレイクする
      break;
    }
  }
  return $result;
}
// ?>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Kosuke_Shibuya

    2017/11/26 15:26

    タイトルと質問内容があっていません。トランザクションではなく、エラー処理では?

    キャンセル

  • oyatsu8

    2017/11/26 15:28

    すみません修正します

    キャンセル

回答 1

checkベストアンサー

+2

材料が空です。

このエラーメッセージは、$_POST["material_name"] がNULLあるいは空文字列の場合に出るものですが、入力フォームを確認すると、name="material_name" のinputがないので、このメッセージとなるのは当然のように思えます。


スクリプトを更に調べると、以下の項目が送られていないようです。

  • id_material
  • id_title
  • title_ja

投稿 2017/11/26 17:02

編集 2017/11/26 17:48

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/26 23:08

    ありがとうございます。確認してみます。

    キャンセル

  • 2017/11/27 02:45

    まだ出来ていないのですが、一つ質問させて頂けないでしょうか、今の自分の正規化でフォームで入力をしてもらう場合は、一つ一つの項目に対してidを入力しないといけなくなってしまうのですが、そんなフォームは見た事がありません、、そのような時に普通はどうするのでしょうか

    キャンセル

  • 2017/11/27 06:46

    まったく別の質問だと思うので、新しい質問として投稿下さい

    キャンセル

  • 2017/11/27 14:28

    ありがとうございます。また別で質問させて頂きます。

    キャンセル

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

ただいまの回答率

91.37%

関連した質問

同じタグがついた質問を見る

  • PHP

    15137questions

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

  • MySQL

    4379questions

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