PHPとMySQLでECサイトをフルスクラッチ開発⑭ECサイトの商品購入決定画面作成
2021-07-21

今回でいよいよECサイト作成も最終段階となります。商品購入の決定画面を作成し、ECサイトをほぼ完成させます。
星マークが作成済のページになります。今回は雲マークの shop_form_check.php shop_form_done.php を作成します。
商品購入が確定すれば、会員登録しているmailアドレスと、サイト運営者のmailアドレスに自動で通知が飛ぶような仕組みにしますので、テストの為に使用できるmailアドレスを2つ用意しておいてください。
テーブルの作成
初めに、会員が商品を購入した情報を登録するテーブルを作成します。
このテーブルに、会員情報と商品の購入履歴の詳細が登録されるようにします。商品発送の手続きや、料金受取の元とになるデータなので非常に重要です。
それでは、MySQLのphp myAdminを立ち上げて、データベース「shop」配下に商品購入のテーブルを作成します。
テーブル名は「dat_sales_product」とします。
カラムは6とし、下図のように「code」「seles_menber_code」「code_product」「price」「quantity」「time」のカラム名、データ型、AI(AUTO_INCREMENT)を設定します。
| カラム名 | データ型 | その他 |
| code | int | AI |
| seles_menber_code | int | – |
| code_product | int | – |
| price | int | – |
| quantity | int | – |
| time | timestamp | – |
codeにプライマリkeyを設定、seles_menber_codeは会員コード、code_productは商品コード、priceは商品単価、quantityは数量、timeは購入が決定した日時になります。
つまり、Aの会員が商品を5つ購入したとすれば、このテーブルに5つレコードが追加されます。
商品購入確認画面
shop_form_check.php
<?php
session_start();
session_regenerate_id(true);
if(isset($_SESSION["menber_login"]) === false) {
print "ログインしてく下さい。<br><br>";
print "<a href='../menber_login/menber_login.html'>ログイン画面へ<br><br></a>";
print "<a href='shop_list.php'>TOP画面へ</a>";
}
if(isset($_SESSION["menber_login"]) === true) {
print "ようこそ";
print $_SESSION["menber_name"];
print "様 ";
print "<a href='../menber_login/menber_logout.php'>ログアウト</a>";
print "<br><br>";
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品購入チェック</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<?php
try {
$menber_code = $_SESSION["menber_code"];
$cart = $_SESSION["cart"];
$kazu = $_SESSION["kazu"];
$max = count($kazu);
$dsn = "mysql:host=localhost;dbname=shop;charset=utf8";
$user = "root";
$password = "";
$dbh = new PDO($dsn, $user, $password);
$dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT name, email, address, tel FROM menber WHERE code=?";
$stmt = $dbh -> prepare($sql);
$data[] = $menber_code;
$stmt -> execute($data);
$rec = $stmt -> fetch(PDO::FETCH_ASSOC);
print "下記内容でよろしいでしょうか?<br><br>";
print "【宛先】<br>";
print "お名前:".$rec['name']."様<br>";
print "mail:".$rec['email']."<br>";
print "ご住所:".$rec['address']."<br>";
print "ご連絡先:".$rec['tel']."<br><br>";
$name = $rec["name"];
$email = $rec["email"];
$address = $rec["address"];
$tel = $rec["tel"];
print "【ご注文内容】<br>";
for($i = 0; $i < $max; $i++) {
$sql = "SELECT name, price, gazou FROM mst_product WHERE code=?";
$stmt = $dbh -> prepare($sql);
$data = array();
$data[] = $cart[$i];
$stmt -> execute($data);
$rec = $stmt -> fetch(PDO::FETCH_ASSOC);
if(empty($rec["gazou"]) === true) {
$disp_gazou = "";
} else {
$disp_gazou = "<img src='../product/gazou/".$rec['gazou']."'>";
}
print "<div class='box'>";
print "<div class='list'>";
print "<div class='img'>";
print $disp_gazou;
print "</div>";
print "<div class='npe'>";
print "商品名:".$rec['name']."<br>";
print "価格:".$rec['price']."円 <br>";
print "数量:".$kazu[$i]."<br>";
print "合計価格:".$rec['price'] * $kazu[$i]."円<br><br>";
$goukei[] = $rec['price'] * $kazu[$i];
print "</div></div></div><br>";
}
$dbh = null;
print "【ご請求金額】---".array_sum($goukei)."円<br><br>";
print "<form action='shop_form_done.php' method='post'>";
print "<input type='hidden' name='name' value='".$name."'>";
print "<input type='hidden' name='email' value='".$email."'>";
print "<input type='hidden' name='address' value='".$address."'>";
print "<input type='hidden' name='tel' value='".$tel."'>";
print "<input type='button' onclick='history.back()' value='戻る'>";
print "<input type='submit' value='OK'>";
print "</form>";
}
catch(Exception $e) {
print "只今障害が発生しております。<br><br>";
print "<a href='../staff_login/staff_login.html'>ログイン画面へ</a>";
}
?>
</body>
</html>
shopディレクトリにshop_form_check.phpを作成します。
このページでは、購入する商品の一覧と、金額、お届け先、を確認させるためのページになります。
はじめに、会員情報、購入しようとしている商品の情報は$_SESSIONの変数に入っているので、その情報を取り出しておきます。
まず、購入者(ログインしている会員情報)の名前や住所などの情報を表示させたいので、データベースに接続後、SQLのSELECT文でmenberテーブルから名前、住所、mail、tel、を選択、fetchで選択したレコードのカラム情報を取り出して、それを表示させています。
次に、ご注文内容を表示させたいので、for文でcartの添え字分だけループさせて、cart内の商品コードを順次取り出して商品のテーブルmst_productからSQLのSELECT文でname, price, gazouを選択、fetchで選択したレコード情報を取り出して順次表示させています。
合計の価格も表示させたいので、ご注文内容をループで表示させている中で、$goukei[]の変数の配列に、順次各商品の価格×数の金額を代入しています。ループを抜けた後、array_sum($goukei) とすれば、$goukeiの配列にある値の合計値が返されるので、これで合計の金額が反映されます。
最後に、購入者の情報をformタグのhiddenでpostして終わりです。
それでは、商品を複数カートに入れ、カート情報から数量などを適当に変更し、購入の手続きへ進んでみて下さい。
商品購入決定画面
shop_form_done.php
<?php
session_start();
session_regenerate_id(true);
if(isset($_SESSION["menber_login"]) === false) {
print "ログインしてく下さい。<br><br>";
print "<a href='../menber_login/menber_login.html'>ログイン画面へ<br><br></a>";
print "<a href='shop_list.php'>TOP画面へ</a>";
exit();
}
if(isset($_SESSION["menber_login"]) === true) {
print "ようこそ";
print $_SESSION["menber_name"];
print "様 ";
print "<a href='../menber_login/menber_logout.php'>ログアウト</a>";
print "<br><br>";
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品購入決定画面</title>
<link rel="stylesheet" href="../style.css">
</head>
<body>
<?php
try {
require_once("../common/common.php");
$post = sanitize($_POST);
$oname = $post["name"];
$email = $post["email"];
$address = $post["address"];
$tel = $post["tel"];
$cart = $_SESSION["cart"];
$kazu = $_SESSION["kazu"];
$max = count($cart);
print $oname."様<br>";
print "ご注文ありがとうございました。<br>";
print $email."にメールを送りましたのでご確認下さい。<br>";
print "商品は入金を確認次第、下記の住所に発送させて頂きます。<br>";
print $address."<br>";
print $tel."<br>";
$honbun = "";
$honbun .= $oname."様\n\nこの度はご注文ありがとうございました\n";
$honbun .= "\n";
$honbun .= "ご注文商品\n";
$honbun .= "-------------\n";
$dsn = "mysql:host=localhost;dbname=shop;charset=utf8";
$user = "root";
$password = "";
$dbh = new PDO($dsn, $user, $password);
$dbh -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
for($i = 0; $i < $max; $i++) {
$sql = "SELECT name, price FROM mst_product WHERE code=?";
$stmt = $dbh -> prepare($sql);
$data[0] = $cart[$i];
$stmt -> execute($data);
$rec = $stmt -> fetch(PDO::FETCH_ASSOC);
$name = $rec["name"];
$price = $rec["price"];
$kakaku[] = $price;
$suryo = $kazu[$i];
$shokei = $price * $suryo;
$honbun .= $name."";
$honbun .= $price."円×";
$honbun .= $suryo."個=";
$honbun .= $shokei."円\n";
}
$sql = "LOCK TABLES dat_sales_product WRITE";
$stmt = $dbh -> prepare($sql);
$stmt -> execute();
for($i = 0; $i < $max; $i++) {
$sql = "INSERT INTO dat_sales_product
(sales_menber_code, code_product,
price, quantity, time)
VALUES(?,?,?,?,now())";
$stmt = $dbh -> prepare($sql);
$data = array();
$data[] = $_SESSION["menber_code"];
$data[] = $cart[$i];
$data[] = $kakaku[$i];
$data[] = $kazu[$i];
$stmt -> execute($data);
}
$sql = "UNLOCK TABLES";
$stmt = $dbh -> prepare($sql);
$stmt -> execute();
$dbh = null;
$honbun .= "送料は無料です。\n";
$honbun .= "-------------\n";
$honbun .= "\n";
$honbun .= "代金は以下の口座にお振込み下さい。\n";
$honbun .= "A銀行 B支店 普通口座 1234567\n";
$honbun .= "入金が確認取れ次第、商品を発送させていただきます。\n";
$honbun .= "\n";
$honbun .= "◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n";
$honbun .= " ~ショップ~\n";
$honbun .= "\n";
$honbun .= "東京都六本木ヒルズ最上階\n";
$honbun .= "電話 090-0000-0000\n";
$honbun .= "メール @kmail.com\n";
$honbun .= "◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆\n";
print "<br>";
print nl2br($honbun);
$title = "ご注文ありがとうございました。";
$header = "From:hellnear@kmail.com";
$honbun = html_entity_decode($honbun, ENT_QUOTES, "UTF-8");
mb_language("Japanese");
mb_internal_encoding("UTF-8");
mb_send_mail($email, $title, $honbun, $header);
$title = "お客様よりご注文が入りました。";
$header = "From:".$email;
$honbun = html_entity_decode($honbun, ENT_QUOTES, "UTF-8");
mb_language("Japanese");
mb_internal_encoding("UTF-8");
mb_send_mail("hellnear@kmail.com", $title, $honbun, $header);
}
catch(Exception $e) {
print "只今障害により大変ご迷惑をおかけしております。";
exit();
}
?>
<br>
<?php $_SESSION["cart"] = array();?>
<?php $_SESSION["kazu"] = array();?>
<a href="shop_list.php">商品画面へ</a>
<br><br>
</body>
</html>
shopディレクトリにshop_form_done.phpを作成します。
このページは、商品購入の受注確定となるページとなるので、その旨を伝えるメッセージ、および会員mail宛に受注内容を自動送信、そして購入情報をデータベースに登録します。
少し長いですが、順にポイントを絞って説明します。
会員情報をpostで受け取り、購入する商品の情報は$_SESSIONで受けとっています。
はじめに、注文確定のコメントを表示させています。
続く$honbun は、会員宛てに送信されるemailに記載される内容になります。htmlの記述にはなりませんので、このページに$honbunに格納した文字列は表示されません。
$honbunに格納した文字列の改行は「¥n」になります。また、「.=」のように、ドット、イコール、で文字列を代入していますが、このようにすることで、文字列をどんどん連結させていくことが可能になります。
したがって、mailの見出しの部分を記述したあと、データベースに接続し、for文でSQLのSELECTで購入した商品の情報を選択し、fetchで取り出した内容を$honbunに代入しています。これで会員宛てのmailには購入情報の詳細までが反映されます。
続くSQLで"LOCK TABLES dat_sales_product WRITE" とありますが、これはテーブルのロック、つまり「排他的制御」を実行しています。
今回の場合は特に使用する意味はありませんが、例えばアクセスが重複し、データベースへの登録に割り込みが発生してはまずい場合(連続してデータベースの登録が必要な場合など)は、テーブルのロックを利用することでアクセスの重複を回避することができます。AとBのアクセスが重複した場合、Aの処理が終わるまではBはアクセス待ち、とする事ができます。
一応今回は、dat_sales_productテーブルにロックをかけます。(複数ロックを掛けたい場合は、LOCK TABLES テーブル名 WRITE, テーブル名 WRITE..とすることで可能です。)
このページでは、dat_sales_productの更新時にロックをかけ、更新が終われば "UNLOCK TABLES" でロックを解除しています。
購入情報を登録するdat_sales_productの更新は、for文で商品の種類分ループをかけて、会員コード、商品コード、価格、合計価格、時間、をSQLのINSERTでレコードの追加しています。
ループ内で$data[] = array(); としているのは、前のSQL実行時の$dataが残っているので、中身を空の状態にする必要があるためです。
データベース登録が終われば、テーブルロックの解除を行い、SQLはもう実行しないのでデータベースを切断します。
そして会員mail宛てに記載する「振込先の銀行の詳細」「ECサイトの情報」などを$honbunに代入しておきます。
※このページの実行時、mailの内容は表示されないと前途しましたが、print nl2br($honbun); と記載する事で、表示を確認する事ができます。テストで表示させたい時に利用するといいですね。確認が終われば、コメントアウトさせておくといいでしょう。
続いて、mail自動送信の記述になります。
$title = "ご注文ありがとうございました。";
$header = "From:hellnear@kmail.com";
$honbun = html_entity_decode($honbun, ENT_QUOTES, "UTF-8");
mb_language("Japanese");
mb_internal_encoding("UTF-8");
mb_send_mail($email, $title, $honbun, $header);
$titleは、mailのタイトルです。
$headerは、送り元のアドレスです。
$honbunは、mailの本文です。このページで「.=」でつないできた文字列ですね。そのHTML エンティティを適切な文字に変換しています。
mb_language("Japanese") mb_internal_encoding("UTF-8"); は、emailのメッセージのエンコーディングとして使用します。
mb_send_mail($email, $title, $honbun, $header); は、引数の内容を、自動で宛先にmail送信する記述になります。第一引数に宛先のmailアドレスを入れています。
ちなみに、この記述がもう一つ下にありますが、これは宛先と送り元のmailアドレスを入れ替えただけのものになります。つまり、購入情報が運営もとにもmailで届くわけですね。
最後に、購入が確定したので、$_SESSIONの内容を array(); で消去しています。
それでは、商品購入手続きの画面で、OKボタンを押してください。下のような画面が表示されるはずです。
赤枠の部分が、通常であればmailで会員のアドレスに飛ぶ内容になります。(print nl2br($honbun);をコメントアウトすれば表示されません。)
下部にWarningのエラーが発生していますが、これは「ローカルで自動mail送信の記述を実行している」からです。
ローカルで実行している場合、mailは宛先に飛ばないようになっているので、エラーが出ます。
mailの確認は、実際にWEBサーバーにアプロードし、公開しなければわかりません。
それでは最後に、データベースを確認してみましょう。購入した情報がしっかりと登録されていればOKです。
もうほぼ完成ですが、次回はカテゴリ別のページの作成と、html/cssでスタイリングして見栄えを良くして、ECサイトのスクラッチ開発を完成させたいと思います。