「簡易在庫管理システム」では、すでにDAOパターンを適用しているため、修正される個所は限られます。
1 <?php
2 class ItemDao extends BaseDao{
3
4 //コンストラクタ
5 function __construct(){
6 parent::__construct();
7 }
8
9 //デストラクタ
10 function __destruct(){
11 parent::__destruct();
12 }
13
14 //全アイテムの取得
15 public function getAllItem(){
16 is_null($this->mysqli) and $this->connect();
17 $result = $this->mysqli->query("SELECT * FROM item");
18 $item_array = array();
19
20 while($row = $result->fetch_array(MYSQLI_ASSOC)){
//<--MYSQLI_NUMではなく
21 $item = new Item();
22 $item->setId($row["id"]);
23 $item->setName($row["name"]);
24 $item->setDetail($row["detail"]);
25 $item->setPrice($row["price"]);
26 $item->setQty($row["qty"]);
27 $item_array[] = $item;
28 }
29 $result->close();
30 return $item_array;
31 }
32
33 //指定されたアイテムの取得
34 private function getItem($sql){
35 is_null($this->mysqli) and $this->connect();
36 $result = $this->mysqli->query($sql);
37
38 $item = null;
39
40 if($result->num_rows != 0){
41 $row = $result->fetch_array(MYSQLI_ASSOC);
42 $item = new Item();
43 $item->setId($row["id"]);
44 $item->setName($row["name"]);
45 $item->setDetail($row["detail"]);
46 $item->setPrice($row["price"]);
47 $item->setQty($row["qty"]);
48 }
49 $result->close();
50
51 return $item;
52 }
53
54 //idでアイテムを取得
55 public function getItemById($id){
56 $id = $this->mysqli->real_escape_string($id);
57 $sql = "SELECT * FROM item WHERE id = '$id'";
58 return $this->getItem($sql);
59 }
60
61 //nameでアイテムを取得
62 public function getItemByName($name){
63 $name = $this->mysqli->real_escape_string($name);
64 $sql = "SELECT * FROM item WHERE name = '$name'";
65 return $this->getItem($sql);
66 }
67
68 //アイテムの更新
69 public function updateItem($item){
70 $item = $this->escapeStringItem($item);
71 is_null($this->mysqli) and $this->connect();
72 $sql = "UPDATE item SET
73 name = '" . $item->getName() . "',
74 detail = '" . $item->getDetail() . "',
75 price = '" . $item->getPrice() . "',
76 qty ='" . $item->getQty() . "'
77 WHERE id = '" . $item->getId() . "'";
78 if( !$this->mysqli->query($sql)){
79 return "更新に失敗しました(1001) " .
$this->mysqli->error . "\n";
80 }
81 return "更新しました";
82 }
83
84 //新規アイテムの登録
85 public function insertItem($item){
86 $item = $this->escapeStringItem($item);
87 is_null($this->mysqli) and $this->connect();
88 //idカラムに空を挿入することで,auto_incrementによる
89 //カウントアップ値を代入できる
90 $sql = "INSERT INTO item values ('',
91 '" . $item->getName() . "',
92 '" . $item->getDetail() . "',
93 '" . $item->getPrice() . "',
94 '" . $item->getQty() . "')";
95 if( !$this->mysqli->query($sql)){
96 return "登録に失敗しました(1002) " . $this->mysqli
->error . "\n";
97 }
98 return "一件追加しました";
99 }
100
101 //指定されたアイテムの削除
102 public function deleteItem($item){
103 return $this->deleteItemById($item->getId());
104 }
105
106 //idで指定されたアイテムの削除
107 public function deleteItemById($id){
108 $id = $this->mysqli->real_escape_string($id);
109 is_null($this->mysqli) and $this->connect();
110
111 $sql = "DELETE FROM item WHERE id = '" . $id . "'";
112 if( !$this->mysqli->query($sql)){
113 $error_no = $this->mysqli->errno;
114 if( $error_no == 1451){
115 return "注文を1度でも受けた商品は在庫一覧から
削除できません<br>(外部キー制約エラー)";
116 }else{
117 return "削除に失敗しました(1003) " . $this->mysqli
->error . "\n";
118 }
119 }
120 return "削除しました";
121 }
122
123 //Itemクラスの各プロパティから特殊文字をエスケープ
124 private function escapeStringItem($item){
125 $item->setId($this->mysqli->real_escape_string($item
->getId()));
126 $item->setName($this->mysqli->real_escape_string($it
em->getName()));
127 $item->setDetail($this->mysqli->real_escape_string($
item->getDetail()));
128 $item->setPrice($this->mysqli->real_escape_string($i
tem->getPrice()));
129 $item->setQty($this->mysqli->real_escape_string($ite
m->getQty()));
130 return $item;
131 }
132 }
133 ?>
|
リスト3 ItemDao.php
まずItemDao.phpを、基底クラスBaseDao.phpを継承するようにします(2行目)。BaseDao.phpを継承することでMySQL接続(connect())/切断手順(disconnect())はBaseDao.phpのものが使用できるようになります。コンストラクタ(__construct)/デストラクタ(__destruct)は、先ほどの説明のようにサブクラスに継承されないため、意図的に親クラスのものを呼び出すよう修正します(4〜12行目)。
次に、前回採用したデータベースの外部キー制約設定に伴う修正を行います。外部キー制約エラーが発生した場合とそれ以外の場合とを区別し、画面にメッセージを表示するようにします。
updateItem()/insertItem()/deleteItem()/deleteItemById()の各メソッドでは、終了結果やエラー内容をreturn文を使って戻すようにします。deleteItemById()ではエラーの際にMySQLサーバから出力されるエラーコードを受け取り(114行目)、1451番(注)であれば外部キー制約エラーの旨を返すようにします(115行目)。
なおsample5では、RDBMSに依存する操作をDAOに集約するため、SQLクエリ中の特殊文字のエスケープは、「mysqli->real_escape_string()」を使ってDAO内で行うよう修正しています(56、63、108、125〜129行目)。
注:第8回の「外部キー制約の利用」中の「DELETE FROM item WHERE id = '3';」実行の際のエラーを参照。
1 <HTML lang="ja">
2 <HEAD>
3 <meta http-equiv="content-type" content="text/html; char
set=UTF-8">
4 <title>在庫管理:在庫一覧</title>
5 </HEAD>
6
7 <?php
8 require_once("Item.php");
9 require_once("BaseDao.php");
10 require_once("ItemDao.php");
11
12 $item = new Item();
13 $item_dao = new ItemDao();
14 ?>
15
16 <BODY TEXT="black" BGCOLOR="white">
17 <!-- タイトル -->
18 <div align="center"><font size="5"><b>在庫管理 </b></fo
nt><font size="3">在庫一覧</b><br></font>
19 </div>
20 <hr width="600" align="center">
21
22 <?php
23 //アイテム一覧
24 foreach($item_dao->getAllItem() as $item){
25
26 $id = $item->getId();
27 $name = $item->getName();
28 $detail = $item->getDetail();
29 $price = $item->getPrice();
30 $qty = $item->getQty();
31 //各アイテムの表示ここから
32 ?>
33
34 <!-- 更新(UPDATE)、削除(DELETE) -->
35 <form action="updateStock.php" method="POST" enctype="ap
plication/x-www-form-urlencoded" name="form">
36 <table border="0" cellspacing="0" cellpadding="7" height
="160" align="center">
37 <tr>
38 <td valign="top" bgcolor="lightgreen">
39 <b>商品ID:<?php print htmlspecialchars($id,ENT_QUOTES);
?></b>
40 <input type=hidden name="id" value="<?php print htmlspeci
alchars($id,ENT_QUOTES); ?>"><br>
41 <b>商品名:</b><input type=text name="name" size="48" val
ue="<?php pri
nt htmlspecialchars($name,ENT_QUOTES); ?>"><br>
42 <b>説明 :</b><br>
43 <textarea name="detail" cols="45" rows="4"><?php print ht
mlspecialchars($detail,ENT_QUOTES); ?></textarea><br>
44 <b>価格:</b><input type=text name="price" value="<?php p
rint htmlsp
ecialchars($price,ENT_QUOTES); ?>" size="5"><b>円/個</b>
45 <b>個数:</b><input type=text name="qty" value="<?php pri
nt htmlspecialchars($qt,ENT_QUOTESy); ?>" size="5"><b>個</b>
46 </td>
47 <td bgcolor="gray" align="center" width="70">
48 <input type="submit" value="UPDATE" name="button"><p>
49 <!-- 本当はこうしたいがIEのためできない <button type="sub
mit" value="UPD name="button">更新</button><p>-->
50 <input type="submit" value="DELETE" name="button"><p>
51 <input type="reset" value="RESET">
52 </td></tr>
53 </table>
54 </form>
55
56 <?
57 //各アイテムの表示ここまで
58 }
59 $item_dao = null;
60 ?>
... 以下省略 ... |
リスト4 displayStock.php
displayStock.phpではBaseDao.phpを読み込むよう、記述を1行加えます(9行目)。HTML出力を行う際はhtmlspecialchars()を使用し、特殊文字のエスケープを行います。SQLクエリに対する特殊文字の処理は、各DAOクラスで行うようにします。
続いて、updateStock.phpにも修正を加えます。
1 <?php
2
3 require_once("Item.php");
4 require_once("BaseDao.php");
5 require_once("ItemDao.php");
6
7 $item = new Item();
8 $item_dao = new ItemDao();
9
10 //フォーム値の取得
11 $item->setId($_POST["id"]);
12 $item->setName($_POST["name"]);
13 $item->setDetail($_POST["detail"]);
14 $item->setPrice($_POST["price"]);
15 $item->setQty($_POST["qty"]);
16
17 switch($_POST["button"]){ //ボタンのラベルで条件分岐
18 case "UPDATE": //更新処理
19 display($item_dao->updateItem($item));
20 break;
21 case "INSERT": //挿入処理
22 display($item_dao->insertItem($item));
23 break;
24 case "DELETE": //削除処理
25 display($item_dao->deleteItem($item));
26 break;
27 default: //それ以外
28 display("指定された処理が不正です");
29 break;
30 }
31
32 //引き渡されたメッセージをHTMLで表示
33 function display($message){
34 print <<<EOS
35 <HTML lang="ja">
36 <HEAD>
37 <meta http-equiv="content-type" content="text/html; char
set=UTF-8">
38 <title>在庫管理:データ更新</title>
39 </HEAD>
40
41 <BODY TEXT="black" BGCOLOR="white">
42 <!-- タイトル -->
43 <div align="center"><font size="5"><b>在庫管理 </b></font><font size="3">データ更新</b><br></font>
44 </div>
45 <hr width="600" align="center">
46
47 <!-- メッセージ -->
48 <p>
49 <div align="center"><font size=+2>$message</font><p>
50 <a href=displayStock.php><font size=+1>在庫一覧へ戻る</fo
nt></a>
51 </div><p>
52
53 <!-- フッター -->
54 <hr width="600" align="center">
55 <table width="600" border="0" align="center">
56 <tr>
57 <td align="right"><font size="2">@IT LinuxSquare「今から
始める MySQL入門」<br>
58 2007/06/25作成</font></td>
59 </tr>
60 </table>
61
62 </BODY>
63 </HTML>
64 EOS;
65 }
66
67 ?>
|
リスト5 updateStock.php
まず4行目のようにBaseDao.phpを読み込みます。ボタンラベルで条件分岐をさせる17行目以降で、単にItemDaoクラスのメソッドを呼び出すだけではなく、メッセージを受け取り、そのメッセージを後半で定義しているdisplay()関数の引数として渡すようにします。
その際、HTML出力を行うときにはhtmlspecialchars()を使用し、特殊文字のエスケープを行います。SQLクエリに対する特殊文字の処理は、ItemDaoクラスで行うようにします。