前提・実現したいこと
PHPでECサイトの購入完了のページを作成中です。
実現したいことは、
カートデータ内の商品をチェックして
「注文数が在庫数より大きい場合、ステータスが公開以外、カートデータが0件の場合」はエラーメッセージを表示する
もしエラーが無ければ、トランザクションを開始し、以下の処理を行う
1.カートの数量を使って商品の在庫数を減算する
2.foreachを使って1商品ずつ取り出し、該当する在庫数を減算する
3.ログインユーザーのカート情報を削除する。
特に、注文数が在庫数より大きい場合とステータスが公開以外、トランザクション処理の部分が分かりません。
自分なりにやってみたのですがうまくいきません。どなたか教えていただけると助かります。
phpmyadminで作成したテーブル情報は以下の通りです。
cartテーブル(ユーザがカートに追加した商品の情報)が
cart_id, user_id, item_id, amount, create_date, update_date
productテーブル(商品情報)が
id, name, price, img, status, create_date, update_date
item_stockテーブル(在庫情報)が
stock_id, item_id, stock, create_date, update_date
です。
発生している問題・エラーメッセージ
エラーメッセージ
該当のソースコード
PHP
1<?php 2// 購入完了のページ 3 4session_start(); 5 6$err_msg = []; //エラーメッセージの格納先 7$success_msg = []; 8$img_dir = './product_picture/'; 9$date = date('Y-m-d H:i:s'); 10 11$host = 'localhost'; //ホスト名 12$username = '9946'; //ユーザー名 13$password = '9946'; //パスワード 14$dbname = '9946'; //データベース名 15$charset = 'utf8'; 16$dsn = 'mysql:dbname='.$dbname.';host='.$host.';charset='.$charset; 17 18 19// もしログインされてない場合は、ログイン画面に強制移動する。 20if(isset($_SESSION['customer']['id']) === FALSE) { 21 header('Location: login.php'); 22 exit(); 23} 24 25if (isset($_SESSION['customer']) === TRUE) { //最初にログインしているかをチェックする。 26 $user_id = $_SESSION['customer']['id']; //ログインページ(login.php)から飛んでくる情報 27 $user_name = $_SESSION['customer']['name']; 28} 29 30// POST以外はエラーメッセージ 31if ($_SERVER['REQUEST_METHOD'] === 'POST') { 32 try { 33 $dbh = new PDO($dsn, $username, $password, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4')); 34 $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 35 $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 36 37 // 現在ログインしているユーザーのカートに入っている商品を全て表示。 38 39 $sql = 'SELECT product.id, name, price, img, status, cart.cart_id, user_id, item_id, amount 40 FROM cart 41 JOIN product 42 ON cart.item_id = product.id 43 WHERE cart.user_id = ?'; 44 $stmt = $dbh->prepare($sql); 45 $stmt->bindValue(1, $user_id, PDO::PARAM_INT); 46 $stmt->execute(); 47 //全て取得するのでfetchALLでレコードを取得する 48 $data = $stmt->fetchALL(); 49 // print_r($data); 50 // exit(); 51 // カート内の商品をforeachを使って合計金額を計算する (HTMLに表示する) 52 $total = 0; 53 54 foreach ($data as $value) { 55 $total += $value['price'] * $value['amount']; 56 } 57 58 // $dataにはカートに入っている商品の情報が入っている 59 // カートデータ内の商品をチェックする 60 // 注文数が在庫数より大きい場合、ステータスが公開以外、カートデータが0件の場合はエラーメッセージ 61 62 63 // 1.注文数が在庫数より大きい場合はエラー 64 foreach ($data as $value) { 65 $item_id = $value['item_id']; 66 if ($value['stock'] - $value['amount'] < 0) { 67 $err_msg[] = ($value['name'] . 'は在庫が足りません。購入可能数:' . $value['stock']); 68 } 69 } 70 71 // 2.カートデータが0件の場合はエラー 72 if (count($data) === 0) { 73 $err_msg[] = '現在カートに商品が入っていません。'; 74 } 75 76 // 3. ステータスが公開以外(1以外)はエラー 77 78 79 // エラーがないときにトランザクション処理を開始 80 // 購入後にカートの中身削除と在庫変動 (cartテーブルとitem_stockにトランザクション処理) 81 82 if (count($err_msg) === 0) { 83 $dbh->beginTransaction(); // トランザクション開始 84 // cartテーブルとitem_stockテーブル 85 86 try { 87 // 現在ログインしているユーザーのカート情報を削除する 88 $sql = 'DELETE FROM cart 89 WHERE user_id = ?'; 90 $stmt = $dbh->prepare($sql); 91 $stmt->bindValue(1, $user_id, PDO::PARAM_INT); 92 $stmt->execute(); 93 94 foreach ($data as $key => $rec) { 95 $stock = (int)$rec['stock'] - (int)$rec['amount']; 96 } 97 // 在庫テーブルを更新する SETで更新対象のカラムと更新後の値を指定 98 // カートの数量を使って商品の在庫数を減算する 99 // foreachで1商品ずつ取り出し、該当する在庫数を減算する 100 $sql = 'UPDATE item_stock 101 SET stock = ?, update_date = ? WHERE item_id = ?'; 102 $stmt = $dbh->prepare($sql); 103 $stmt->bindValue(1, $stock, PDO::PARAM_INT); 104 $stmt->bindValue(2, $date, PDO::PARAM_STR); 105 $stmt->bindValue(3, $item_id, PDO::PARAM_INT); 106 $stmt->execute(); 107 $carts = $dbh->commit(); 108 $success_msg[] = '在庫数を更新しました。'; 109 } catch (PDOException $e) { 110 // ロールバック処理 111 $dbh->rollback(); 112 $err_msg[] = '在庫数の更新に失敗しました。' . $e->getMessage(); 113 } 114 } 115 116 } catch (PDOException $e) { 117 $err_msg[] = 'カート内の商品情報が取得できませんでした。理由:'.$e->getMessage(); 118 } 119} else { 120 $err_msg[] = '要求の形式が正しくありません'; 121} 122?> 123<!DOCTYPE html> 124<html lang="ja"> 125 <head> 126 <meta charset="UTF-8"> 127 <title>購入完了ページ</title> 128 <style> 129 td { 130 text-align: center; 131 } 132 .total { 133 color: #f00; 134 font-weight: bold; 135 font-size: 30px; 136 text-align: center; 137 } 138 139 .img { 140 margin-bottom: 20px; 141 } 142 143 .finish-msg { 144 margin-top: 20px; 145 height: 80px; 146 font-size: 1.4em; 147 text-align: center; 148 line-height: 80px; 149 background-color: #f5c9c6; 150 } 151 </style> 152 </head> 153 154 <body> 155 <h1 class="finish-msg">ご購入ありがとうございました!</h1> 156 <a href="logout.php">ログアウト</a> 157 <!-- 購入した商品 --> 158<?php if (count($data) > 0){ ?> 159 <table> 160 <thead> 161 <tr> 162 <th>商品画像</th> 163 <th>商品名</th> 164 <th>価格</th> 165 <th>購入数</th> 166 <th>小計</th> 167 </tr> 168 </thead> 169 <tbody> 170<?php foreach ($data as $value) { ?> 171 <tr> 172 <td><img class="img" src="<?php echo $img_dir . $value['img']; ?>" width=160 height=160></td> 173 <td><?php echo($value['name']); ?></td> 174 <td><?php echo($value['price']); ?></td> 175 <td><?php echo($value['amount']); ?></td> 176 <td><?php echo($value['price'] * $value['amount']); ?></td> 177 </tr> 178<?php } ?> 179 </tbody> 180 </table> 181 182 <p class="total">合計金額:¥<?php echo($total); ?></p> 183<?php } else { ?> 184 <p>カートに商品はありません。</p> 185<?php } ?> 186 187 </body> 188 189</html>
試したこと
ここに問題に対して試したことを記載してください。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー