PHPとMySQLでECサイトをフルスクラッチ開発⑥商品管理のデータベース、追加のPHPファイル作成
2021-07-21
今回より、商品管理ページの作成にはいります。
基本的にはスタッフ管理ページの応用でPHPファイルが作れますが、新たに「画像」データの登録がありますので、データベースへのファイルのアップロードや上書き、削除の仕組みが学べるかと思います。また、価格を半角数字のみ受け付ける「正規表現」も登場します。
それでは初めに、商品管理画面の作成の流れから説明しようと思います。
商品登録画面作成の流れ
図のような流れの登録画面を作成します。スタッフ管理画面の構図とほぼ同じです。
星マークのログインページは作成済みですので、とりあえず今回は、雲マークの商品追加ページとなるpro_add.php~pro_add_done.phpまでを作成します。
まだdbに商品登録のテーブルがないので、とりあえずテーブルから作成します。
テーブルの作成
それでは商品の登録テーブルを作成します。
ここに登録された商品が、最終的には公開するECサイトに表示されるようになります。
XAMPPのMySQLを立ち上げて、データベース「shop」配下に商品管理のテーブルを作成します。
テーブル名は「mst_product」とします。
カラムは6とし、下図のように「code」「category」「name」「price」「gazou」「explanation」のカラム名、データ型、AI(AUTO_INCREMENT)を設定します。
カラム名 | データ型 | その他 |
code | int | AI |
category | varchar 値10 | – |
name | varchar 値30 | – |
price | int | – |
gazou | varchar 値30 | – |
explanation | varchar 値100 | – |
codeにプライマリkeyを設定、これが商品コードになります。categoryは商品のカテゴリ、nameは商品名、priceは商品の価格、gazouは商品のイメージ画像、explanationは商品の紹介文を入れることとします。
PHPファイルの作成場所
スタッフ管理画面のフォルダと同じく、xamppのApacheのドキュメントルートhtdocs配下に「product」フォルダを作成します。
商品管理ページは「product」フォルダ配下にどんどんphpファイルを作成していきます。
あと、productフォルダ内に、「gazou」というフォルダも作成しておいてください。これは画像データのアップロード先として使用します。
それでは、今回はまず「pro_add.php」~「pro_add_done.php」のファイルを作成します。
追加商品情報入力画面
pro_add.php
<?php session_start(); session_regenerate_id(true); if(isset($_SESSION["login"]) === false) { print "ログインしていません。<br><br>"; print "<a href='staff_login.html'> ログイン画面へ</a>"; exit(); } else { print $_SESSION["name"]."さんログイン中"; 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> <form action="product_add_check.php" method="post" enctype="multipart/form-data"> 商品追加<br><br> カテゴリー<br> <?php require_once ("../common./common.php");?> <?php print pulldown_cate();?> <br><br> 商品名<br> <input type="text" name="name"> <br><br> 価格<br> <input type="text" name="price"> <br><br> 画像<br> <input type="file" name="gazou"> <br><br> 詳細<br> <textarea name="comments" style="width: 500px; height: 100px;"></textarea> <br><br> <input type="button" onclick="history.back()" value="戻る"> <input type="submit" value="OK"> </form> </body> </html>
productフォルダに、pro_add.phpを作成します。
pro_add.phpにアクセスすると下のような画面が表示されます。
※まだログインのページからつながっていないので、ログイン確認のsession記述はコメントアウトしておくといいでしょう。このあと作成する2つのページも、コメントアウトしておいてください。
追加する商品のカテゴリ、商品名、価格、画像、商品の説明文、を入力するページになります。
formタグで各種入力欄を表示させますが、今回は「画像」のアップロードボタンを加えているので、formタグに新しい記述が増えています。
enctype="multipart/form-data">
の部分ですね。これを記述しなければ、submitボタンを押した時に画像のデータがpost送信されません。そしてformタグの配下に、
<input type="file" name="gazou"> を記述しています、これが「ファイルを選択」のボタンになります。
したがって、画像などのデータをアップロードする際には、この2つの記述がformタグで必要になります。
あと、textareaタグですが、これはコメントなどの比較的長い文章を入力したい時に使用します。デフォルトのボックスサイズが小さいので、今回はcssを埋め込んで広げていますが、外部で読み込ませても問題ありません。
最後に、カテゴリのプルダウンメニューですが、こちらは関数が入っているcommonファイルをインクルードして、新しく作成したpulldown_cate();の関数を実行させています。今後もプルダウンメニューがちょくちょく出てきますので、関数にしておくと便利です。それでは、commonファイルに下記コードを追加してください。
function pulldown_cate() { print "<select name='cate'>"; print "<option value='食品'>食品</option>"; print "<option value='家電'>家電</option>"; print "<option value='書籍'>書籍</option>"; print "<option value='日用品'>日用品</option>"; print "<option value='その他'>その他</option>"; print "</select>"; }
関数名はpulldown_cate() とします。引数は空白としているので、関数名()だけで登録しているプルダウンメニューが表示されます。
プルダウンメニューは <serect>タグで<option>タグを囲むことで表示されます。
valueは値で、optionタグの間にある文字は、そのまま画面に表示される文字列です。
したがって、selectのnameがcateになっているので、submitを押せばプルダウンで選択しているvalueがpostで送信されます。
今回は5つのカテゴリを作成しました。
商品入力チェック(半角数字正規表現チェック)
pro_add_check.php
<?php session_start(); session_regenerate_id(true); if(isset($_SESSION["login"]) === false) { print "ログインしていません。<br><br>"; print "<a href='staff_login.html'> ログイン画面へ</a>"; exit(); } else { print $_SESSION["name"]."さんログイン中"; 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 require_once("../common/common.php"); $post = sanitize($_POST); $name = $post["name"]; $price = $post["price"]; $gazou = $_FILES["gazou"]; $comments = $post["comments"]; $cate = $post["cate"]; print $cate."<br><br>"; if(empty($name) === true) { print "商品名が入力されていません。 <br><br>"; } else { print $name; print "<br><br>"; } if(preg_match ("/\A[0-9]+\z/", $price) === 0) { print "正しい値を入力してください。 <br><br>"; } else { print $price."円"; print "<br><br>"; } if($gazou["size"] > 0) { if($gazou["size"] > 1000000) { print "ファイルのサイズが大きすぎます。 <br><br>"; } else { move_uploaded_file ($gazou["tmp_name"],"./gazou/ ".$gazou["name"]); print "<img src='./gazou/ ".$gazou['name']."'>"; print "<br><br>"; } } if(empty($comments) === true) { print "詳細が入力されていません。"; print "<br><br>"; } if(mb_strlen($comments) > 100) { print "文字数は100文字が上限です。"; print "<br><br>"; } else { print $comments; print "<br><br>"; } if(empty($name) or preg_match ("/\A[0-9]+\z/", $price) === 0 or $gazou["size"] > 1000000 or empty($comments) or mb_strlen($comments) > 100) { print "<form>"; print "<input type='button' onclick='history.back()' value='戻る'>"; print "</form>"; } else { print "上記商品を追加しますか?<br><br>"; print "<form action= 'product_add_done.php' method='post'>"; print "<input type='hidden' name='cate' value='".$cate."'>"; print "<input type='hidden' name='name' value='".$name."'>"; print "<input type='hidden' name='price' value='".$price."'>"; print "<input type='hidden' name='gazou' value='".$gazou['name']."'>"; print "<input type='hidden' name='comments' value='".$comments."'>"; print "<input type='button' onclick='history.back()' value='戻る'>"; print "<input type='submit' value='OK'>"; print "</form>"; } ?> </body> </html>
productフォルダに、pro_add_check.phpを作成します。
このページでは、商品名、価格、コメントが入力されているか、価格が半角数字であるか、コメントが100文字以内であるか、アップロードしたい画像のサイズ(容量)が1MB以下であるか、をチェックし、問題なければ次ページへ内容をpost送信するページです。
まず、お馴染みのsanitize関数でpostのデータをエスケープします。
画像のデータは、$_FILES[] で受け取れます。そしてこの$_FILSE[]には、データだけでは無く、画像サイズ(容量)、画像データの名前、送り元のフォルダ名、等が格納されています。
はじめのif文で、商品の名前が入力されているかの確認をしています。
続いてのif文ですが、これは「正規表現」と呼ばれるもので、今回は「半角数字」が入力されているかの確認をしています。正規表現されていれば1となり、NGなら0、となります。
記述の詳細については、preg_match(正規表現、正規表現したい値)となります。したがって、$priceが半角数字で入力されているかの確認になります。上のコードでは¥標記が\になっていますが、どちらでも問題はありません。¥に直すと、半角数字の正規表現は、
"/¥A[0-9]+¥z/" になります。
続くif文は、画像アップロードされていれば、サイズが1MB以下であるかの確認をしています。1MB以上なら、NGとなるようになっています。
前途したように、$_FILES[]には多くの情報が入っているので、画像のサイズを確認したい場合は、$_FILES["size"]とすれば分かります。今回は$gazouに代入しているので、$gazou["size"]ですね。
その後、画像データがあり、かつ1MB以下ならば、gazouフォルダへデータをアップロードする記述に入ります。
move_uploaded_file($gazou["tmp_name"],"./gazou/".$gazou["name"]); の部分ですね。
少しややこしいですが、move_uploaded_file がアップロードの命令文で、引数には、
(元の保存場所、アップロード先、ファイル名)を指定しなければなりません。したがって、
($gazou["tmp_name"],(元の保存場所)"./gazou/"(保存先).$gazou["name"](ファイル名)); となります。
アップロードが出来れば、そのまま画像を表示させたいので、htmlのimg src で表示させます。
prinr "<img src='./gazou/".$gazou['name']."'>";
./は、同じ階層を表しています。このように画像のやり取りの記述は、ドットやクオーテーションにクセがあります。少しややこしいですが、間違えると正しくプログラムが動きません。
続いて、コメントが入力されているかを確認し、コメントがあれば100文字以下であるか、を確認しています。
mb_strlen($comments) > 100 の部分ですね。
mb_strlenは、引数にいれた値の文字列の長さを計算します。
そして、名前の入力、価格の正規表現、画像のサイズ、コメントの入力をチェックし、一つでもNGがあれば前のページへ戻るように誘導しています。
全てクリアできれば、formタグで入力した情報をhiddenで次ページのpro_add_done.phpへpost送信します。
画像については、無しでも登録できるようになっています。
長くなりましたが、pro_add.phpで適当に商品を入力してみて、正規表現でちゃんと半角以外はNGなるか、コメントは100文字以上でNGになるか、など、試してみて下さい。
OKなら、下のような感じになります。
商品をデータベースに追加
pro_add_done.php
<?php session_start(); session_regenerate_id(true); if(isset($_SESSION["login"]) === false) { print "ログインしていません。<br><br>"; print "<a href='staff_login.html'> ログイン画面へ</a>"; exit(); } else { print $_SESSION["name"]."さんログイン中"; 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); $name = $post["name"]; $price = $post["price"]; $gazou = $post["gazou"]; $comments = $post["comments"]; $cate = $post["cate"]; $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 = "INSERT INTO mst_product (category, name, price, gazou, explanation) VALUES(?,?,?,?,?)"; $stmt = $dbh -> prepare($sql); $data[] = $cate; $data[] = $name; $data[] = $price; $data[] = $gazou; $data[] = $comments; $stmt -> execute($data); $dbh = null; } catch(Exception $e) { print "只今障害が発生しております。<br><br>"; print "<a href='../staff_login/ staff_login.html'>ログイン画面へ</a>"; exit(); } ?> 商品を追加しました。<br><br> <a href="product_list.php">スタッフ一覧へ</a> </body> </html>
productフォルダに、pro_add_done.phpを作成します。
ここまでくれば簡単ですね。
postデータをエスケープして受け取ります。
データベース接続後、SQLのINSERT文で各カラムの値を登録し、実行するだけです。
登録できれば、追加した旨のコメントを表示させて、商品一覧ページへ誘導します。
次回、商品一覧ページを作成しますので、今の段階で各項目ごとに2商品づつ、登録しておいてください。
追加後、データベースに登録されているかも確認しておきます。