ショッピングカートPro

 以前からKOMONETサイトでは配布していたんですが、修正に修正を重ね、かなり機能的に充実して来たと思われますので、この辺で一度詳しく解説しておこうかと思います。それでは、よろしく_(._.)_

*注意…尚、今回のスクリプトはPHP4.2.0以降のスーパーグローバル変数に対応したものになっています。

ファイル構成

 このスクリプトは、商品管理用のgoods.phpとそのログ保存用のgoods.dat、そして、ショッピングカート本体のkomoshop.phpとの3つのファイルから構成されます。他にもタイトル用の画像ファイルなどがありますが、直接スクリプトとは関係ないので、ここでは説明を省きます。

 尚、商品画像を保存する為のフォルダimgが必要です。書き込みができなくてはいけないので、パーミッションは「777」又は「707」にして下さい。

商品管理用スクリプト goods.php ----- ログ保存用ファイル goods.dat

↓発注   商品在庫数の修正↑

ショッピングカート本体 komoshop.php

商品画像保存用フォルダ img

機能概要

 まずこのスクリプトは、商品管理用のgoods.phpにおいて、販売商品を画像も含めてWeb上から管理できると言う利点があります。これは、ここの「画像掲示板」と「日記帳」との応用によって作られています。登録した商品情報は、ログ保存用ファイルgoods.datに全て記録されています。

 次にショッピングカート本体のkomoshop.phpですが、こちらには新たに、受注した商品の在庫数を自動修正する機能が追加されています。これにより、在庫数がなくなった場合は、商品管理用のgoods.phpにおいて商品の注文が出来なくなる事は言うまでもありません。

 では、具体的にそれぞれのスクリプトのコード内容を見て行きましょう。

商品管理用スクリプト「goods.php」

 このスクリプトは、管理者のみが商品データの書き込み・修正ができ、しかも商品画像も一緒に管理できると言った結構多機能なスクリプトになっています。

<HTML>
<HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
 <TITLE>KOMOショッピング</TITLE>
 <STYLE TYPE="text/css">
 <!--
 :link   {
       Color : blue ;
       Text-Decoration : None
      }
 :active {
       Color : blue ;
       Text-Decoration : None
      }
 :visited {
       Color : blue ;
       Text-Decoration : None
      }
 A:hover {
       Color : blue ;
       Text-Decoration : UnderLine
      }
 -->
 </STYLE>
</HEAD>
<BODY BGCOLOR="#FFFBF0">
<CENTER>
<P ALIGN="CENTER"><IMG SRC="shop_title.gif" WIDTH="345" HEIGHT="53" ALIGN="BOTTOM" BORDER="0">
<P><B><FONT COLOR="#990066">Web上で商品管理が出来ます。登録データの修正も可能です!(^o^)丿</FONT></B></P>
<P>パスワードは「777」です。お好きな商品画像をアップできます。</P>
通常のHTML表示部分です。
<?php
//============================初期設定==============================
$data_file = './goods.dat'; //データログ用ファイル
$php_pass = './komoshop.php'; //ショッピングカート・スクリプト名
$passwd = '777'; //管理者用パスワード
$data_max = 50; //データ最大記録数
$page_view = 5; //1ページの記事表示件数
$up_dir = '/img/'; //商品画像データ保存フォルダ名
$path = dirname($_SERVER["PATH_TRANSLATED"]).$up_dir;
$w_max = 200; //画像の横幅の最大値(ピクセル)
$h_max = 200; //画像の縦幅の最大値(ピクセル)
$PHP_SELF = './goods.php';
初期設定部分です。皆さんの環境に合わせて、それぞれの値を変更して下さい。
if($_POST['action'] == "regist"){
 //フォームデータの取得
 $code = $_POST['code'];
 $g_name = $_POST['g_name'];
 $fname = $_POST['fname'];
 $price = $_POST['price'];
 $expl = $_POST['expl'];
 $g_amount = $_POST['g_amount'];
 $button = $_POST['button'];
 $upfile = $_FILES['upfile']['tmp_name'];
 $upfile_name = $_FILES['upfile']['name'];
処理内容が書き込み「regist」の場合です。

まず、フォームデータから各変数の値を取得します。
 //処理の分岐
 if($button == "修正/更新"){
  //ここから書き込みデータの調整
  $g_name = str_replace(" ", "&#95;",$g_name); //空白対策
  $g_name = str_replace(" ", "&#95;",$g_name);
  $price = str_replace(",", "&#44;",$price); //桁区切りのコンマ対策
  $expl = htmlspecialchars($expl);
  $expl = nl2br($expl);
  $expl = str_replace("\r", "", $expl);
  $expl = str_replace("\n", "", $expl);
  //ログファイルの区切文字(",")と区別するために文字コード(&#44)に書き換える。
  $expl = str_replace(",", "&#44;",$expl);
  $repdata = file($data_file);
  $fp = fopen($data_file, "w");
  for($i=0; $i<count($repdata); $i++){
   list($rcode,$rname,$rfname,$rprice,$rexpl,$ramount) = split( ",", $repdata[$i]);
   if ($code == $rcode) {
    $repdata[$i] = "$code,$g_name,$fname,$price,$expl,$g_amount\n";
    fputs($fp, $repdata[$i]);
   }else{
    fputs($fp, $repdata[$i]);
   }
  }
  fclose($fp);
変数$buttonの値が「修正/更新」の時の処理です。

まずお決まりの、書き込みデータの調整を行います。ここはもう説明は要らないですね(^^ゞ

次にログファイルを開き、ループ処理の中で、記事コードが合致すれば、データを修正又は更新しています。
 }elseif($button == "削除"){
  $deldata = file($data_file);
  $fp = fopen($data_file, "w");
  for($i=0; $i<count($deldata); $i++){
   list($dcode,$dname,$dfname,$dprice,$dexpl,$damount) = split(",", $deldata[$i]);
   if ($code == $dcode) {
    $deldata[$i] = "";
    if($dfname){
     unlink(".".$up_dir.$dfname);
    }
   }
   fputs($fp, $deldata[$i]);
  }
  fclose($fp);
変数$buttonの値が「削除」の時の処理です。

これも上記の処理同様、ログファイルを開き、ループ処理の中で、記事コードが合致すれば、データを空白にして削除しています。同時に、画像ファイルの登録があれば、画像ファイル自体も一緒に削除しています。

★int unlink ( string filename )関数・・・引数filename で指定されたファイルを削除します。成功すると0を返し、エラーの時はfalseを返します。
 }else{
  if($g_name){
   $code = time(); //アクセス時の秒数
   //ここから書き込みデータの調整
   $g_name = str_replace(" ", "&#95;",$g_name); //空白対策
   $g_name = str_replace(" ", "&#95;",$g_name);
   $price = str_replace(",", "&#44;",$price); //桁区切りのコンマ対策
   $expl = htmlspecialchars($expl);
   $expl = nl2br($expl);
   $expl = str_replace("\r", "", $expl);
   $expl = str_replace("\n", "", $expl);
   //ログファイルの区切文字(",")と区別するために文字コード(&#44)に書き換える。
   $expl = str_replace(",", "&#44;",$expl);
ここは処理内容が純粋に新規書き込みの場合のものです。

もし商品名$g_nameの値があれば、書き込み処理を行います。ここはお決まりの、書き込みデータの調整部分です。
   if($upfile){
    $source = $upfile;
    $source_name = $upfile_name;
    $source_name = ereg_replace("^(.:.*\\\\)?(.*)", "\\2", $source_name);
    if(($source != "none")&&($source != "")){
     $dest = $path.$source_name;
     if(copy($source,$dest)){
      $imagesize = getimagesize($dest);
      switch($imagesize[2]){
       case 0:
        unlink($dest);
        break;
       case 1:
        $out = $code.".gif";
        rename($dest,$path.$out);
        break;
       case 2:
        $out = $code.".jpg";
        rename($dest,$path.$out);
        break;
       case 3:
        $out = $code.".png";
        rename($dest,$path.$out);
        break;
      }
     }
    }
   }
   $fname = $out;
アップする画像がある場合の処理です。

詳しくは「画像掲示板」で解説していますので、そちらをご参照下さい。

処理内容としては、アップされた画像ファイルを指定されたフォルダ内にコピーして、画像の種類に応じてそのファイル名をGIF、JPG、PNGの拡張子を持ったファイル名に変更しています。配列変数
imagesize[2]の値が、画像ファイルの種類を表しています。

ここでは、ファイル名
$codeにはアクセス時の秒数を利用しています。

最後に、コピーされた画像ファイルの新たなファイル名が生成された場合にのみ、ログファイルに記録するアップ画像ファイル名
$fnameを生成するようになっています。
   //配列要素を文字列により連結
   $input_msg = implode(",", array($code,$g_name,$fname,$price,$expl,$g_amount));
   $message = file($data_file);
   $fp = fopen($data_file, "w");
   rewind($fp);
   fputs($fp, "$input_msg\n");
   //最大記録数の調整
   if($data_max <= count($message)){
    $msg_num = $data_max - 1;
   }else{
    $msg_num = count($message);
   }
   for($i = 0; $i < $msg_num; $i++){
    fputs($fp, $message[$i]);
   }
   fclose($fp);
   unset($message);
  }
 }
ここはお決まりの記事書き込み処理の部分です。
}elseif(($_POST['action'] == "edit") && ($_POST['password'] == $passwd)){
 $kanri_flag = 1;
 //フォームデータの取得
 $e_code = $_POST['e_code'];
 if($e_code < 1){
  echo "<form action=$PHP_SELF method=POST ENCTYPE=multipart/form-data>\n";
  echo "<input type=hidden name=action value=regist>\n";
  echo "<table border=0>\n";
  echo "<tr><td align=right>商品名:</td><td><input type=text size=25 name=g_name></td></tr>\n";
  echo "<tr><td align=right>商品画像:</td><td><INPUT TYPE=file NAME=upfile SIZE=35><FONT SIZE=2 COLOR=#CC0000> *GIF、JPG、PNG画像のみ有効。</FONT></td></tr>\n";
  echo "<tr><td align=right>提供価格:</td><td><input type=text size=25 name=price></td></tr>\n";
  echo "<tr><td align=right>商品説明:</td><td><textarea name=expl rows=6 cols=50></textarea></td></tr>\n";
  echo "<tr><td align=right>在庫数:</td><td><input type=text size=10 name=g_amount></td></tr>\n";
  echo "</table>\n";
  echo "<input type=submit value=登録/更新> <input type=reset value=リセット>\n";
ここは管理者専用の編集画面に入った時の処理です。パスワードで保護されています。

まずページ最後の管理窓の表示切り分け用に、フラグ$kanri_flagを立てます。

新規登録の場合($e_code < 1)は、新規登録の為のフォームのみを表示します。

変数
$e_codeは、各登録商品に持たせた識別番号を表しますから、この番号が1より小さいと言う事は、新規登録である事を表します。
 }else{
  $comdata = file($data_file);
  for($i=0; $i<count($comdata); $i++){
   list($ccode,$cname,$cfname,$cprice,$cexpl,$camount) = split(",", $comdata[$i]);
   if ($e_code == $ccode) {
    $g_name2 = $cname; $fname2 = $cfname; $price2 = $cprice; $expl2 = $cexpl; $g_amount2 = $camount;
    $expl2 = str_replace("<br />", "\n", $expl2);
    break;
   }
  }
  unset($comdata);
  echo "<form action=$PHP_SELF method=POST ENCTYPE=multipart/form-data>\n";
  echo "<input type=hidden name=action value=regist>\n";
  echo "<input type=hidden name=code value=$e_code>\n";
  echo "<input type=hidden name=fname value=$fname2>\n";
  echo "<table border=0>\n";
  echo "<tr><td align=right>商品名:</td><td><input type=text size=25 name=g_name value=$g_name2></td></tr>\n";
  echo "<tr><td align=right>提供価格:</td><td><input type=text size=25 name=price value=$price2></td></tr>\n";
  echo "<tr><td align=right>商品説明:</td><td><textarea name=expl rows=6 cols=50>$expl2</textarea></td></tr>\n";
  echo "<tr><td align=right>在庫数:</td><td><input type=text size=10 name=g_amount value=$g_amount2></td></tr>\n";
  echo "</table>\n";
  echo "<input type=submit name=button value=修正/更新> <input type=submit name=button value=削除>\n";
 }
 echo "</form>\n";
}
ここは管理者専用の編集画面において、登録商品の情報を修正しようとした時のフォーム生成処理部分です。

まずログファイルから商品情報を読み出し、指定の商品コードが一致した場合、該当の商品情報を各変数に代入しています。そして、読み込んだ変数を各フォーム項目の値に代入して表示しています。
if($message = file($data_file)){
 //フォームデータの取得
 $pline = $_POST['pline'];
 $msg_count = count($message);
 if($pline == ""){
  $p_line = 0;
 }else{
  $p_line = $pline;
 }
 $end_data = $msg_count - 1;
 $page_end = $p_line + ($page_view - 1);
 if($page_end >= $end_data)
 $page_end = $end_data;
登録された商品情報があれば、それを表示します。

この部分は、1ページの記事表示数を調整する為の処理です。詳しくは「掲示板」の解説内容をご参照下さい。
 for($i = $p_line; $i <= $page_end; $i++){
  list($vcode,$vname,$vfname,$vprice,$vexpl,$vamount) = split( ",", $message[$i]);
  echo "<table border=0 width=600 cellspacing=0 bgcolor='blue'>\n";
  echo "<tr><td width=100%><table border=0 width=100% bgcolor='white'>\n";
  echo "<form action=$PHP_SELF method=POST>\n";
  echo "<input type=hidden name=action value=edit>\n";
  echo "<input type=hidden name=e_code value=$vcode>\n";
  echo "<tr><td colspan=2><font color='blue' size=4><b>■ $vname</b></font>\n";
  $vprice2 = number_format($vprice);
  if($vamount < 1){ $vamount = 0; }
  echo "<b>[商品価格]</b>¥ $vprice2<b>[在庫数]</b>$vamount\n";
  if (($_POST['action'] == 'edit') && ($_POST['password'] == $passwd)) {
   echo "<input type=hidden name=password value=$passwd> <input type=submit value=訂正>\n";
  }
  echo "</td></tr>\n";
  echo "<tr>";
ループ処理で、該当ページ内の登録記事内容を表示して行きます。

ここは、各商品情報の商品名、商品価格、在庫数を表示させる部分です。
  if($vfname && file_exists("$path$vfname")){
   $size = getimagesize("$path$vfname");
   $img_w=$size[0];
   $img_w2 = 600 - $img_w;
   $img_h=$size[1];
   if($img_w > $w_max || $img_h > $h_max){
    $w_ritu = $w_max / $img_w;
    $h_ritu = $h_max / $img_h;
    ($w_ritu < $h_ritu) ? $key = $w_ritu : $key = $h_ritu;
    $width = (int) $img_w * $key;
    $height = (int) $img_h * $key;
    $width2 = 600 - $width;
    echo "<td width=$width>";
    echo "<A HREF=.$up_dir$vfname TARGET=_blank><img src=.$up_dir$vfname WIDTH=" . $width . " HEIGHT=" . $height . "></A></td><td width=$width2 valign=top>";
   }else{
    echo "<td width=$img_w>";
    echo "<img src=.$up_dir$vfname></td><td width=$img_w2 valign=top>";
   }
  }else{
   echo "<td colspan=2>";
  }
ログファイルに商品画像のファイル名が登録されており、且つその画像ファイル自体も存在する場合に、画像ファイルのサイズを調整して表示します。詳しくは「画像掲示板」の解説をご参照下さい。

画像を表示するセルの幅を、画像の幅サイズに合わせています。又、右の解説文を表示するセル内の表示位置をトップに指定しています。

画像を表示しない場合は、表組みのセルを右に結合します。
  if($vexpl){
   echo "$vexpl";
  }else{
   echo "&nbsp;";
  }
商品の解説文$vexplがあれば表示します。
  echo "</td></tr></form>\n";
  echo "<tr><td colspan=2>\n";
  echo "<form action=$php_pass method=POST>\n";
  echo "<input type=hidden name=action value=regist>\n";
  echo "<input type=hidden name=code value=$vcode>\n";
  echo "<input type=hidden name=goods value=$vname>\n";
  $vprice = str_replace("&#44;", "", $vprice);
  echo "<input type=hidden name=price value=$vprice>\n";
ここは商品を注文する為のフォーム生成部分です。

隠れ属性(hidden)で各項目の値を持たせています。
  echo "<B>注文数:</B>\n";
  if($vamount > 0){
   echo "<SELECT NAME=amount>\n";
   for($j=1;$j<=$vamount;$j++){
    echo "<OPTION VALUE=$j>" . $j . "</OPTION>\n";
   }
   echo "</SELECT>\n";
  }else{
   echo "<font color='red'>在庫切れ</font>\n";
  }
  echo "<input type=submit value=買物カゴへ入れる></td></tr></form></table></td></tr></table><br>\n";
 }
?>
注文数を指定する部分は、在庫数から自動でドロップダウンリストを使って、注文可能な数量を表示できるようにしています。ループ処理を使っています。

在庫数がない場合は、「在庫切れ」を赤色で表示します。
<P>
<TABLE BORDER="0" WIDTH="600">
 <TR>
  <TD WIDTH="50%">

<?php
 if($page_end >= $page_view){
  $page_count = floor($page_end / $page_view);
  $prev_line = ($page_count - 1) * $page_view;
  print "<form method=Post action=$PHP_SELF>\n";
  if (($_POST['action'] == 'edit') && ($_POST['password'] == $passwd)){
   echo "<input type=hidden name=action value=edit>\n";
   echo "<input type=hidden name=password value=$passwd>\n";
  }
  print "<input type=hidden name=pline value=$prev_line>\n";
  print "<input type=submit value=前のページ>\n";
  print "</form>\n";
 }else{
  print "&nbsp;\n";
 }
?>

  </TD>
ここは、条件が合えば「前のページ」ボタンを表示させる処理部分です。

★int floor ( float number )関数・・・引数number の小数点以下を切り捨てた値を返します。

管理者専用の編集画面におけるページ移動の場合は,隠れ属性でactionとpasswordの値を持たせるようにしています。
  <TD WIDTH="50%"><P ALIGN="RIGHT">

<?php
 $next_line = $page_end + 1;
 if($page_end != $end_data){
  print "<form method=Post action=$PHP_SELF>\n";
  if (($_POST['action'] == 'edit') && ($_POST['password'] == $passwd)){
   echo "<input type=hidden name=action value=edit>\n";
   echo "<input type=hidden name=password value=$passwd>\n";
  }
  print "<input type=hidden name=pline value=$next_line>\n";
  print "<input type=submit value=次のページ>\n";
  print "</form>\n";
 }else{
  print "&nbsp;\n";
 }
?>

  </TD>
 </TR>
</TABLE>
ここは、従来の「次のページ」ボタンを表示させる処理部分です。

管理者専用の編集画面におけるページ移動の場合は,隠れ属性でactionとpasswordの値を持たせるようにしています。
<?php
 echo "<form action=$php_pass method=POST>\n";
 echo "<input type=submit value=買物カゴの中身を見る></form>\n";
 echo "<hr>\n";
}
「買物カゴの中身を見る」ボタンを表示させます。
if($kanri_flag < 1){
 echo "<div align=left>\n";
 echo "<form action=$PHP_SELF method=POST>\n";
 echo "<input type=hidden name=action value=edit>\n";
 echo "<input type=password size=10 name=password>\n";
 echo " <input type=submit value=管理><br>\n";
 echo "</form></div>\n";
}
?>
編集画面でない通常表示の場合は、管理者専用の編集画面に入る為のフォーム部品を表示します。

判断基準は上で立てたフラグ
$kanri_flagの値です。
</CENTER>
</BODY>
</HTML>
HTML表示を閉じます。

ショッピングカート本体「komoshop.php」

 新たに在庫数の自動修正機能を追加しました。従来の機能については、詳しくは「ショッピングカート(完成版)」のページをご参照下さい。

<?php
//===============初期設定===================
$title = 'KOMOショッピングカート';
$title_img = './title.gif'; //タイトル用画像ファイル
$goback = './goods.php'; //商品ページへのパス
$subject = '「PHPの小部屋」サンプルスクリプトより';
$to = '*****@***.ne.jp'; //メール送信先
$taskrate = 5; //消費税率(%)。取らない時は0に設定する。
$PHP_SELF = './komoshop.php';
$S_Cookie = $HTTP_COOKIE_VARS{"S_Cookie"}; //クッキーデータの取得
$data_file = './goods.dat'; //データログ用ファイル
$remail = 1; //返信メールを出すなら1、出さないなら0。
$subject2 = '「KOMOショッピングカート」ご注文確認メール(自動配信)'; //返信メールのタイトル
$message = "この度はご注文有難うございました。以上の内容でご注文を受け付けました。"; //返信メールに添付するメッセージ
初期設定部分です。

[機能追加部]
赤色部分は、お客が発注処理をした後、その内容確認メールを自動で返信する為の初期設定です。

変数$remailの値で、返信メールを発信するかどうか選択できます。変数$subject2は返信メールのタイトルです。変数$messageは、発注内容を表示した後に付け加える、お客へのメッセージです。
//===============クッキー処理================
if($_POST['action'] == "regist"){
 //フォームデータの取得
 $code = $_POST['code'];
 $goods = $_POST['goods'];
 $price = $_POST['price'];
 $amount = $_POST['amount'];
 
if($amount > 0){
  $goods_flag = 0;
  if(isset($S_Cookie)){
   while(list($g_num, $value) = each($S_Cookie)){
    list($code2,$goods2,$price2,$amount2) = split(",", $value);
    if($goods == $goods2){
     $goods_flag++;
     break;
    }
   }
  }
  if($goods_flag < 1){

   $g_num = time(); //クッキー識別番号を現在の秒数からゲット 
…@
   $value = "$code,$goods,$price,$amount";
   setcookie("S_Cookie[$g_num]", $value); //ブラウザを閉じるとリセット
   echo "<META HTTP-EQUIV=refresh content=0;URL=$PHP_SELF>"; 
…A
   exit;
  
}else{
   $errmsg = "<FONT COLOR='red'>同じ商品を重複して注文できません。やり直して下さい。</FONT>";
  }
 }else{
  $errmsg = "<FONT COLOR='red'>注文数量がゼロです。やり直して下さい。</FONT>";
 }
クッキー処理の部分です。HTML表示よりも先に処理をしなくてはいけません。

[修正部分](赤色部分)
 注文数が0以上の場合のみ処理を行うよう修正しました。これで在庫数がない商品を注文しようとしてもエラーになります。
 又、同じ商品を重複して注文できないよう修正しました。フラグ「
$goods_flag」を立て、条件分岐の判断材料に使うようにしています。

@商品を注文した際の処理です。クッキー配列変数を使っています。

Aクッキーを有効にする為、再読み込みをしています。
}elseif($_POST['action'] == "remove"){
 //フォームデータの取得
 $g_num = $_POST['g_num'];
 setcookie("S_Cookie[$g_num]", "", time()-3600); //クッキーを削除
 echo "<META HTTP-EQUIV=refresh content=0;URL=$PHP_SELF>";
 exit;
注文商品を一軒ずつ削除する為の処理部分です。クッキーの書き込みで、わざわざ過去の時刻を指定して削除しているのは、従来の処理でエラーが発生した為です。
}elseif($_POST['action'] == "delete"){
 while(list($g_num, $value) = each($S_Cookie)){
  setcookie("S_Cookie[$g_num]", "", time()-3600); //クッキーを順に全て削除
 }
 echo "<META HTTP-EQUIV=refresh content=0;URL=$PHP_SELF>";
 exit;
}
?>
商品発注後にクッキーを全て削除する場合の処理です。ループ処理を使っています。
<HTML>
<HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
 <TITLE><?php echo $title; ?></TITLE>
 <STYLE TYPE="text/css">
 <!--
 :link {
   Color : blue ;
   Text-Decoration : None
  }
 :active {
   Color : blue ;
   Text-Decoration : None
  }
 :visited {
   Color : blue ;
   Text-Decoration : None
  }
 A:hover {
   Color : blue ;
   Text-Decoration : UnderLine
  }
 -->
 </STYLE>
</HEAD>
<BODY topmargin="0" leftmargin="0">
<CENTER>
<P>
<TABLE BORDER="0" CELLSPACING="0" WIDTH="100%" HEIGHT="50" BACKGROUND="./top_back.gif">
 <TR>
  <TD WIDTH="100%">
   <P ALIGN="CENTER"><IMG SRC="<?php echo $title_img; ?>" WIDTH="391" HEIGHT="31" ALIGN="BOTTOM" BORDER="0">
  </TD>
 </TR>
</TABLE>
</P>
<P><A HREF="JavaScript:history.back();" onMouseOver="this.style.color='red'" onMouseOut="this.style.color='blue'">一つ前のページへ</A> <A HREF="<?php echo $goback; ?>" onMouseOver="this.style.color='red'" onMouseOut="this.style.color='blue'">商品ページへ</A></P>
通常のHTML表示部分です。
<?php
if($errmsg){
 echo $errmsg;
 exit;
}
[修正個所]
上のクッキー処理の際にエラーが発生した場合は、エラーメッセージを表示して、これ以降の処理を
exitで抜けます。(忘れてました。すみません。)

if($_POST['action'] == "send"){
 //フォームデータの取得
 $name = $_POST['name'];
 $pcode = $_POST['pcode'];
 $addr = $_POST['addr'];
 $tel = $_POST['tel'];
 $email = $_POST['email'];
 $comment = $_POST['comment'];
 $sum = $_POST['sum'];
注文メールを送信する際の処理です。

まず各項目のフォームデータを取得します。
 $from = $email;
 $header = "From: $from";
 $msg = "";
 while(list($g_num, $value) = each($S_Cookie)){
  list($dcode,$dgoods,$dprice,$damount) = split(",", $value);
  
$dprice = number_format($dprice);
  
$msg .= "ご注文 = 商品名 $dgoods (価格 $dprice 円)×数量 $damount\n";
  $repdata = file($data_file);
  $fp = fopen($data_file, "w");
  for($i=0; $i<count($repdata); $i++){
   list($rcode,$rname,$rfname,$rprice,$rexpl,$ramount) = split( ",", $repdata[$i]);
   if($dcode == $rcode){
    $new_amount = $ramount - $damount;
    $repdata[$i] = "$rcode,$rname,$rfname,$rprice,$rexpl,$new_amount\n";
    fputs($fp, $repdata[$i]);
   }else{
    fputs($fp, $repdata[$i]);
   }
  }
  fclose($fp);
 }
ループ処理を使って、クッキーに書き込まれた注文内容を羅列して行きます。返信メール用に、注文内容を分かり易く表示するようにしました。

この処理の中で、ログファイルの中身を開いて、商品番号が合致した場合に、在庫数から注文数を差し引く処理をしています。

この部分は、本当はメール送信処理が成功した場合に実行したかったのですが、エラーが発生した為、ここで処理するようにしました。
 if($taskrate){ $msg .= "消費税率 = $taskrate %\n"; }
 
$sum = number_format($sum);
 $msg .= "合計 = $sum 円\n";
 $msg .= "お名前 = $name\n";
 if($pcode){ $msg .= "郵便番号 = $pcode\n"; }
 $msg .= "ご住所 = $addr\n";
 if($tel){ $msg .= "電話番号 = $tel\n"; }
 $msg .= "E-mail = $email\n";
 if($comment){ $msg .= "一言どうぞ = $comment\n"; }
商品発注の為のメール内容を成形します。合計金額も分かり易く三桁区切りにフォーマットしています。
 if(mb_send_mail($to, $subject, $msg, $header)){
  echo "<P>発注メールは無事送信されました。有難うございました。</P>\n";
  echo "<P><FONT COLOR='red'>クッキーを全て削除したい場合は、下の「クッキー削除」ボタンを押して下さい。</FONT></P>\n";
  echo "<FORM ACTION=$PHP_SELF METHOD=POST>\n";
  echo "<INPUT TYPE=HIDDEN NAME=action VALUE=delete>\n";
  echo "<INPUT TYPE=SUBMIT VALUE=クッキー削除></FORM></P>\n";
  
if($remail > 0){
   $header = "From: $to";
   $msg2 = "==ご注文内容===========================\n";
   $msg2 .= $msg;
   $msg2 .= "=======================================\n";
   $msg2 .= "$message\n";
   mb_send_mail($email, $subject2, $msg2, $header);
  }

 }else{
  echo "<P><FONT COLOR='red'>発注メールの送信に失敗しました。もう一度やり直して下さい。</FONT></P>\n";
  echo "<META HTTP-EQUIV=refresh content=3;URL=$PHP_SELF?action=recover>";
 }
発注メールの送信に成功した場合と、失敗した場合の処理です。

失敗した場合、自動修正した在庫数を元に戻さなくてはいけないので、再読み込み処理で「action=recover」を指定しています。

[機能追加部]
赤色部分は、お客が発注処理をした時、その発注メールが正常に送信できた場合に、その内容確認メールを自動配信する為の処理部分です。

注文内容の部分は、変数$msgでそっくりそのまま流用しています。後は、メールアドレスを上と逆に設定しているだけです。

変数$remailの値で、自動返信するかどうか選択できます。
}elseif($_GET['action'] == "recover"){
 while(list($g_num, $value) = each($S_Cookie)){
  list($dcode,$dgoods,$dprice,$damount) = split(",", $value);
  $repdata = file($data_file);
  $fp = fopen($data_file, "w");
  for($i=0; $i<count($repdata); $i++){
   list($rcode,$rname,$rfname,$rprice,$rexpl,$ramount) = split( ",", $repdata[$i]);
   if($dcode == $rcode){
    $new_amount = $ramount + $damount;
    $repdata[$i] = "$rcode,$rname,$rfname,$rprice,$rexpl,$new_amount\n";
    fputs($fp, $repdata[$i]);
   }else{
    fputs($fp, $repdata[$i]);
   }
  }
  fclose($fp);
 }
 echo "<P><FONT COLOR='red'>商品データを復旧しました。もう一度やり直して下さい。</FONT></P>\n";
発注メールの送信に失敗した場合に、自動修正した在庫数を元に戻す為の処理です。上と逆の事をしています。
}else{
 if(isset($S_Cookie)){
  echo "<CENTER><TABLE BORDER=1 CELLSPACING=0>\n";
  echo "<TR><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>商品名</FONT></B></TD><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>価格</FONT></B></TD><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>数量</FONT></B></TD><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>小計</FONT></B></TD><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>削除</FONT></B></TD></TR>\n";
  while(list($g_num, $value) = each($S_Cookie)){
   list($dcode,$dgoods,$dprice,$damount) = split(",", $value);
   $dprice3 = number_format($dprice);
   $damount3 = number_format($damount);
   $shoukei = (integer)$dprice * (integer)$damount;
   $shoukei3 = number_format($shoukei);
   $goukei += $shoukei;
   echo "<TR><TD>$dgoods</TD><TD>\ $dprice3</TD><TD>$damount3</TD><TD>\ $shoukei3</TD>\n";
   echo "<TD><FORM ACTION=$PHP_SELF METHOD=POST>\n";
   echo "<INPUT TYPE=HIDDEN NAME=action VALUE=remove>\n";
   echo "<INPUT TYPE=HIDDEN NAME=g_num VALUE=$g_num>\n";
   echo "<INPUT TYPE=SUBMIT VALUE=削除></TD></TR></FORM>\n";
  }
  $goukei3 = number_format($goukei);
  echo "<TR><TD BGCOLOR=#ccffff COLSPAN=3><B>合計</B></TD><TD BGCOLOR=#ccffff COLSPAN=2><B>\ $goukei3</B></TD></TR>\n";
  echo "</TABLE><BR>\n";
商品陳列ページから商品を買物カゴに入れた際の処理です。

クッキーに書き込まれた内容があれば、買物カゴの中身を一覧表示します。
  if($taskrate > 0){
   $task = (integer)$goukei * (integer)$taskrate / 100;
   $task3 = number_format($task);
   $sougoukei = (integer)$goukei + (integer)$task;
   $sougoukei3 = number_format($sougoukei);
   echo "<TABLE BORDER=1 CELLSPACING=0>\n";
   echo "<TR><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>消費税</FONT></B></TD><TD BGCOLOR=#66CCCC><B><FONT COLOR='white'>総合計</FONT></B></TD></TR>\n";
   echo "<TR><TD>\ $task3</TD><TD>\ $sougoukei3</TD></TR></TABLE><BR>\n";
  }
消費税率が設定されている場合の処理です。

注文商品一覧の下に、消費税と、消費税を含んだ総合計金額を表示します。
  if($_POST['action'] == "kakunin"){
   //フォームデータの取得
   $name = $_POST['name'];
   $pcode = $_POST['pcode'];
   $addr = $_POST['addr'];
   $tel = $_POST['tel'];
   $email = $_POST['email'];
   $comment = $_POST['comment'];
発注の際の確認画面を表示する為の処理です。

まず各項目の値をフォームデータから取得します。
   if($name && $addr && $email){
    
if(preg_match("/[\w\d\-\.]+\@[\w\d\-\.]+/", $email)){
     echo "<P>ご注文の内容に間違いがなければ、下の「送信」ボタンを押して下さい。</P>\n";
     echo "<FORM ACTION=$PHP_SELF METHOD=POST>\n";
     echo "<INPUT TYPE=HIDDEN NAME=action VALUE=send>\n";
     if($taskrate > 0){
      echo "<INPUT TYPE=HIDDEN NAME=sum VALUE=$sougoukei>\n";
     }else{
      echo "<INPUT TYPE=HIDDEN NAME=sum VALUE=$goukei>\n";
     }
     echo "<TABLE BORDER=1 CELLSPACING=0>\n";
     echo "<TR><TD><B>お名前</B></TD><TD>$name</TD></TR>\n";
     echo "<INPUT TYPE=HIDDEN NAME=name VALUE=\"$name\">\n";
     if($pcode){
      echo "<TR><TD><B>郵便番号</B></TD><TD>$pcode</TD></TR>\n";
      echo "<INPUT TYPE=HIDDEN NAME=pcode VALUE=\"$pcode\">\n";
     }
     echo "<TR><TD><B>ご住所</B></TD><TD>$addr</TD></TR>\n";
     echo "<INPUT TYPE=HIDDEN NAME=addr VALUE=\"$addr\">\n";
     if($tel){
      echo "<TR><TD><B>電話番号</B></TD><TD>$tel</TD></TR>\n";
      echo "<INPUT TYPE=HIDDEN NAME=tel VALUE=\"$tel\">\n";
     }
     if($email){
      echo "<TR><TD><B>E-mail</B></TD><TD>$email</TD></TR>\n";
      echo "<INPUT TYPE=HIDDEN NAME=email VALUE=\"$email\">\n";
     }
     if($comment){
      $comment2 = nl2br($comment); //HTML改行文字の挿入
      echo "<TR><TD><B>一言どうぞ</B></TD><TD>$comment2</TD></TR>\n";
      echo "<INPUT TYPE=HIDDEN NAME=comment VALUE=\"$comment\">\n";
     }
     echo "</TABLE><BR>\n";
     echo "<INPUT TYPE=SUBMIT VALUE=送信></FORM>\n";
    }else{
     echo "<P><FONT COLOR='red'>メールアドレスの書式が無効です。前のページに戻ってやり直して下さい。</FONT></P>\n";
    }
   }else{
    echo "<P><FONT COLOR='red'>必須事項が記入されていません。前のページに戻ってやり直して下さい。</FONT></P>\n";
   }
商品を発注する際、必須項目に記入漏れがなければ、発注の為の確認画面を表示します。又、preg_match関数で変数$emailの値がメールアドレスとして有効かどうか判別しています。有効な場合のみ、確認画面を表示しています。

必須項目に記入漏れがあけば、警告文を表示します。
  }else{
   echo "ご注文がお決まりになりましたら、下の申込欄に必要事項をご記入の上、発注ボタンを押して下さい。\n";
   echo "<FORM ACTION=$PHP_SELF METHOD=POST>\n";
   echo "<INPUT TYPE=HIDDEN NAME=action VALUE=kakunin>\n";
   echo "<TABLE BORDER=0>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>お名前</B></TD><TD><INPUT TYPE=TEXT NAME=name SIZE=40> <FONT COLOR='red' SIZE=2>*必須!</FONT></TD></TR>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>郵便番号</B></TD><TD><INPUT TYPE=TEXT NAME=pcode SIZE=15></FONT></TD></TR>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>ご住所</B></TD><TD><INPUT TYPE=TEXT NAME=addr SIZE=60> <FONT COLOR='red' SIZE=2>*必須!</FONT></TD></TR>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>電話番号</B></TD><TD><INPUT TYPE=TEXT NAME=tel SIZE=20></TD></TR>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>E-mail</B></TD><TD><INPUT TYPE=TEXT NAME=email SIZE=30> <FONT COLOR='red' SIZE=2>*必須!</FONT></TD></TR>\n";
   echo "<TR><TD BGCOLOR=#CCFFFF><B>一言どうぞ</B></TD><TD><TEXTAREA NAME=comment ROWS=5 COLS=50></TEXTAREA></TD></TR></TABLE><BR>\n";
   echo "<INPUT TYPE=SUBMIT VALUE=発注する> <INPUT TYPE=RESET VALUE=書き直す></FORM>\n";
  }
商品を発注する為の、お客様情報を入力するフォームを表示します。
 }else{
  echo "<P>現在選択された商品はございません。</P>\n";
 }
}
?>
クッキーに書き込まれた内容がなければ、この一文を表示します。
</CENTER>
</BODY>
</HTML>
HTML文を閉じます。

 *上の内容をこのまま複写しても動きません。何故なら、表示を見やすくする為コード中に全角スペースが入っているからです。実際にお使いになる時は、この点を修正してからサーバにアップして下さい。

HOME