今度はconfirm.phpに修正を加えます。
1 <?php
2 require_once("BaseDao.php");
3 require_once("Order_item.php");
4 require_once("Item.php");
5 require_once("ItemDao.php");
6
7 session_start();
8 //注文番号の確認
9 isset($_SESSION["order_no"]) or die("不正な呼び出しです");
10
11 //フォームの値から注文を取り出し、$order_itemを生成
12 //さらに$order_itemを配列$order_item_arrayに格納
13 $order_item_array = array();
14
15 foreach($_POST as $idx => $val){
16 if($idx != "order_no" && $val > 0){ //注文番号以外で,
注文個数が1個以上
17 $order_item = new Order_item();
18 $order_item->setItem($idx);
19 $order_item->setQty($val);
20 $order_item_array[] = $order_item;
21 }
22 }
23 if(count($order_item_array) <= 0){
24 //何も注文されていない場合
25 die("一品以上ご注文ください");
26 }
27
28 //order_item_arrayをセッション変数に格納
29 $_SESSION["order_item_array"] = $order_item_array;
30 ?>
31
32 <HTML lang="ja">
33 <HEAD>
34 <meta http-equiv="content-type" content="text/html;
charset=UTF-8">
35 <title>オンラインストア:確認</title>
36
37 <SCRIPT TYPE="text/javascript">
38 <!--
39 //submitの二重押し対策
40 function disableButton(){
41 if(check()){
42 document.form1.button1.disabled = true;
43 submitForm();
44 }
45 }
46 function submitForm(){
47 document.form1.submit();
48 }
49 //入力漏れチェック
50 function check(){
51 if(document.form1.name.value == ""){
52 window.alert('お名前が未入力です');
53 return false;
54 }else if(document.form1.zip_code.value == ""){
55 window.alert('〒番号が未入力です');
56 return false;
57 }else if(document.form1.address.value == ""){
58 window.alert('住所が未入力です');
59 return false;
60 }else{
61 return true;
62 }
63 }
64 // -->
65 </SCRIPT>
66 </HEAD>
... 以下省略 ...
86 <?php
87 $item = new Item();
88 $item_dao = new ItemDao();
89
90 $total_price = 0;
91 $total_qty = 0;
92
93 //配列$order_item_arrayから$order_itemを取り出す
94 foreach($order_item_array as $order_item){
95 $item = $item_dao->getItemById($order_item->getItem());
96 if(is_null($item)){
97 die("商品アイテムが見つかりません");
98 }
99
100 //小計
101 $subtotal_price = $item->getPrice() * $order_item->get
Qty();
102 //合計
103 $total_price += $subtotal_price;
104 $total_qty += $order_item->getQty();
105 //注文商品の表示ここから
106 ?>
107
108 <!-- 商品ID <?php print htmlspecialchars($item->getId(),
ENT_QUOTES); ?>-->
109 <tr>
110 <td><b><?php print htmlspecialchars($item->getName(),ENT
_QUOTES); ?></b></td>
111 <td align="right"><?php print htmlspecialchars($item->g
etPrice(),ENT_QUOTES); ?> 円</td>
112 <td align="right"><?php print htmlspecialchars($order_i
tem->getQty(),ENT_QUOTES); ?> 個</td>
113 <td align="right"><?php print htmlspecialchars($subtota
l_price,ENT_QUOTES); ?> 円</td>
114 </tr>
115
116 <?php
117 //注文商品の表示ここまで
118 }
119 $item_dao = null;
120 ?>
... 以下省略 ...
131 <table align="center">
132 <tr>
133 <td>お名前:</td><td><input type=text name="name"
size="20" maxlength="20"></td>
134 </tr>
135 <tr>
136 <td>〒番号:</td><td><input type=text name="zip_code"
size="9" maxlength="9"><b>(※「-」ハイフンなし)</b></td>
137 </tr>
138 <tr>
139 <td>住所 :</td><td><input type=text name="address"
size="50" maxlength="100"></td>
140 </tr>
141 </table>
142 <p>
143 <div align="center">
144 <input type="button" value="購 入" onClick="disable
Button()" name="button1"> <input
type="reset" name="リセット">
145 </div>
146 </form>
|
リスト7 confirm.php
confirm.phpでは、注文内容をフォームデータ($_POST)から取得します。商品アイテムごとの注文情報は「$_POST["商品id"]=注文個数」で取り出すことができます。15行目では$_POSTからキーを抜き出し「$idx => $val」でキーに対する値を取得しています(foreach($配列 as $キー => $変数))。
フォームデータ($_POST)には注文番号など商品以外の情報が含まれています。商品の情報だけを抜き出すように条件を設けます(16行目)。
Order_itemクラスを生成後(17行目)、セッターを使って商品idと注文個数を設定します(18、19行目)。Order_itemクラスは注文を受けた商品の個数分作成されます。処理を容易にするため配列に格納します(20行目)。何も注文がない場合は25行目のようなメッセージを出力し、処理を中断します。配列の要素数は「count($配列)」で調べることができます(23行目)。
Order_itemクラスが格納された配列を、次の画面であるpurchase.phpに引き渡すよう、セッション変数に格納します(29行目)。セッション変数には文字列や数値型のような基本型以外にも、オブジェクトをそのまま格納することができます。注文内容の確認のために出力されるリストは、この配列から再度Order_itemクラスを取り出し(94行目)、Order_itemクラスのゲッターで商品idや個数を取得します(95、101、104、112行目)。
商品名や単価は、先ほど取得した商品idを基に、ItemDaoクラスを通してItemクラスを生成し(95行目)、各値を拾い出します(101、108、110、111行目)。HTML出力を行う際はhtmlspecialchars()を使用し、特殊文字のエスケープを行います。SQLクエリに対する特殊文字の処理は、各DAOクラスで行うようにします。
confirm.phpでは、住所/氏名に加え郵便番号も入力できるようテキストフィールド(zip_code)を追加しています(135〜137行目)。JavaScriptの入力漏れチェックも同様に追加します(54〜56行目)。
なお今回は、各入力項目の入力規制は設けていません。ですがこのままでは、郵便番号欄に半角数字以外の文字が入力されるなど、想定していない文字列が登録される危険性があります。入力規制の方法については、次回説明を加えます。
続いてpurchase.phpに修正を加えます。
1 <?php
2 require_once("BaseDao.php");
3 require_once("Order_item.php");
4 require_once("Order_main.php");
5 require_once("Order_mainDao.php");
6 require_once("Item.php");
7 require_once("ItemDao.php");
8
9 session_start();
10 //注文番号の確認
11 isset($_SESSION["order_no"]) or die("不正な呼び出しです");
12 //注文情報の確認
13 isset($_SESSION["order_item_array"]) or die("不正な呼び
出しです");
14
15 $order_main = new Order_main();
16 $order_main_dao = new Order_mainDao();
17
18 //フォーム値、セッション値の変数展開
19 $order_no = $_SESSION["order_no"];
20 $now = date("Y/m/d H:i:s", time());
21 $name = $_POST["name"];
22 $zip_code = $_POST["zip_code"];
23 $address = $_POST["address"];
24
25 $order_main->setOrder_no($order_no);
26 $order_main->setOrder_date($now);
27 $order_main->setName($name);
28 $order_main->setZip_code($zip_code);
29 $order_main->setAddress($address);
30
31 //注文の重複確認
32 if(!is_null($order_main_dao->getOrder_mainByOrder_no
($order_no))){
33 die("すでに注文済みです");
34 }
35
36 //セッション変数から配列$order_item_arrayを取り出し
$order_itemへ展開
37 //order_noとorder_dateを設定する
38 $order_item_array = $_SESSION["order_item_array"];
39 foreach($order_item_array as $order_item){
40 $order_item->setOrder_no($order_no);
41 $order_item->setOrder_date($now);
42 }
43
44 //注文情報をDBに格納
45 if(!$order_main_dao->insertOrder_main_item($order_
main,
$order_item_array)){
46 die("登録に失敗しました");
47 }
48
49 //セッション変数の無効化
50 $_SESSION = array();
51 session_destroy();
52 ?>
... 以下省略 ...
|
リスト8 purchase.php
注文を確定するpurchase.phpでは、MySQLに関連する処理をDAOに切り離します。注文番号は重複のみ確認(32行目)します。本システムが払い出した注文番号以外が使用されていないか、不正な注文番号が使用されていないかなど、厳密な判定は割愛しているため注意してください。
重複がなければ処理を続行し、注文情報をorder_itemテーブルとorder_mainに登録します。この際、MySQLサーバに対するトランザクション処理(45行目)はOrder_mainDaoクラスで行います。purchase.phpではその結果を受け取り、エラーを表示するか、注文が確定したことを画面に表示します。
なおSQLクエリに対する特殊文字の処理は、各DAOクラスで行うようにします。
今回までで、この簡易オンラインショッピングサイトの大まかな処理の解説は終了です。次回はフォーム入力値のチェック方法やAjaxのバックエンドで動作するPHPなど、ユーザーインターフェイスを充実させる方法を紹介します。