5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ファミレスのメニューシステムもどき作ってみた

Last updated at Posted at 2021-12-02

しばらくぶりにシステム作ってみました。
飲食店のチェーン店でタブレットのメニューシステムを見てた時、「作れそうかも」と思ったこと。

ですがPHPはまだまだ初心者。想像しながらの穴だらけ試作システムです。
DBも初めて連携しました。

やりたいこと

  • DBからメニューを書出し
  • メニュー注文機能の作成(追加、変更、削除)
  • 検索システム

ブラウザからDBにメニューを入れる管理システムも作ってみました。
▶︎ファミレスのメニューもどき管理画面を作ってみた

下記が相関関係図です。
relation.jpg

##トップページ index.php
XDでざっくりデザイン作成後、HTMLとCSSで組み立て。
こんな感じのUIです。
menutop.png
メニューボックスをクリックするとメニュー注文へ。

▶︎サンプルサイトはこちら

共通のDB接続はパーツ化してインクルード。
DBからSELECTで全データを取得後配列化。

index.php
//DB接続のインクルードは省略
//DBより一覧表書き出し
  $sql_list = 'SELECT * FROM menulist order by ID ASC';
  $stmt = $dbh->prepare($sql_list);
  $stmt->execute();
  
  $data =array();
  $count = $stmt->rowCount();//レコード数取得
  while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $data[] = $row;

メニュー一覧はカテゴリーごとにまとめたかったので、それぞれforeachでループしました。
カテゴリーの順番も任意で。
メインの後にドリンクがくると何かしっくりいかないし、やはりサラダ、スープ、前菜など順番は大切かなと。

foreachの中にifでカテゴリーごとにループさせるのは分かったのですが、
if($row['category'] == 'メイン') だといちいちカテゴリーごとにブロックを書かないといけないので、面倒い。時間を置いて考えて、for文で試してみました。

$cat_listという配列を手作り。任意の順番で並べたかったので下記のように記述。
$cat_list = ['メイン','サラダ','スープ','サイドメニュー','麺・パスタ','デザート','ドリンク'];

それぞれのsectionに同一ページスクロール用のidも付けたかったのでid用の配列も作成。
$cat_listの内容と順番を合わせておきます。
$category_id = ['mainmenu','salad','soup','sideMenu','pasta','dessert','drink'];

forの$iはforeachの中で使うとうまく出力しなかったので外側で変数に代入。
$cat_item = $cat_list[$i];

index.php
<?php for($i = 0; $i < count($cat_list); $i++): ?>
        <!-- $iはforeachの中に入れるとちゃんと表示されないので外で変数にした -->
        <?php $cat_item = $cat_list[$i]; ?>
        <!-- idを付与 -->
      <section id="<?php echo $category_id[$i]; ?>">
        <h2 class="catTitle"><span>Category</span><?php echo $cat_list[$i]; ?></h2>
        <ul class="menuBox">
        <?php foreach($data as $row): ?>
        <!-- カテゴリーごとにまとめて書き出し -->
          <?php if($row['category'] == $cat_item): ?>
            <li class="selectOrder">
              <div class="img">
                <img src="<?php echo $img_path.$row['image']; ?>" alt="">
                <p class="cart">注文する</p>
              </div>
              <div class="details">
                <p class="material"><?php echo $row['material']; ?></p>
                <p class="menuName">商品名<span><?php echo $row['item']; ?></span></p>
                <dl>
                  <dt>金額</dt>
                  <dd><span class="orderPlic"><?php echo number_format($row['plice']); ?></span><span class="smallText">(税込)</span></dd>
                </dl>
              </div>
            </li>
            <!-- //.selectOrder -->
          <?php endif; ?>
        <?php endforeach; ?>
        </ul>
      </section>
    <?php endfor; ?>

思うようにリスト化出来ました。
嬉しい。

###注文確認フォーム
注文確認フォームは移行せず、同一ページ内で最初は非表示にしてメニューBOXがクリックされたらformが表示。
選んだアイテムだけが書き出されるようjsで操作。
ここはcount数で悩まされました。
jsで++countを置いているので、初期値を-1に
<input id="count" type="hidden" name="count_menu" value="-1">

bace.js
//submitで持っていく値の個数と番号の変数
  let count;
  //商品をクリックしたら注文リストへ
  jQuery('.selectOrder').on('click',function(){
    //選んだ商品データを変数に入れておく
    const orderName = jQuery('.menuName span',this).text();
    const orderImg = jQuery('.img img',this).attr('src');
    const orderPlice = jQuery('.orderPlic',this).text();
    //カウントを取得しておかないとおかしくなる
    count = jQuery('#count').attr('value');
    //count位置重要
    ++count;

    //TOP注文リスト表示、メニュー一覧非表示
    jQuery('#orderBox').css('display','block');
    jQuery('#header,#main').css('display','none');
    //追加・変更ページ
    jQuery('#orderChangeBox').css('display','block');
    jQuery('#headerChange,#mainChange').css('display','none');
    //注文の商品名、値段、画像、個数を書き出し、カウント数と合わせておく
    //tableの中に要素書き出し
    jQuery('#orderMenu,#changeMenu').append('<tr><th class="orderName">'+orderName+'</th><td class="orderImg"><img src="'+orderImg+'" alt=""></td><td class="orderOneplice">'+orderPlice+'円<span class="smallText">(税込)</span><img src="image/icon_x.svg" alt=""></td><td class="num"><input type="number" name="num'+count+'" min="1" max="50" value="1">個</td><td><p class="deleteMenu">削除<img src="image/icon_x.svg" alt=""></p></td></tr>');
    
    //name属性+カウント数でgetで持っていく値と数を指定
    jQuery('#count').before('<input type="hidden" name="title'+count+'" value="'+orderName+'"><input type="hidden" name="plice'+count+'" value="'+orderPlice+'"><input type="hidden" name="img'+count+'" value="'+orderImg+'">');
    jQuery('#count').attr('value',count);
  });

  //MENU削除
  jQuery(document).on('click', '.deleteMenu', function(){
    //デリートボタンを押したtrのみを削除
    jQuery(this).parents('tr').remove();
    //現在のカウントを取得
    count = jQuery('#count').attr('value');

    //削除によって揃わなくなった個数と順番の連動を合わせる
     for(let i=0; i < count; ++i){
       jQuery('input[name^="title"]').eq(i).attr('name','title'+i);
       jQuery('input[name^="plice"]').eq(i).attr('name','plice'+i);
       jQuery('input[name^="num"]').eq(i).attr('name','num'+i);
       jQuery('input[name^="img"]').eq(i).attr('name','img'+i);
       }

    //1個ずつ持っていく数を減らす
    --count; 
    jQuery('#count').attr('value',count);

    //確認リストから商品がなくなったらメニュー一覧を表示
    if(count < 0){
      jQuery('#orderBox,#orderChangeBox').css('display','none');
      jQuery('#header,#main,#headerChange,#mainChange').css('display','block');
    }
  });

jQueryでappendメソッドで後から追加した要素にclickイベントを効かせるようにするには要素に対してではなく、documentに対してイベントを設定しないとダメみたいです。

受け取り先の$_GETでは
for($i = 0; $i < $count_menu+1; $i++)
こうすると数が合うようになりました。

order.php
$count_menu = isset($_GET['count_menu']);
//XSS関数作成html_escape()
$count_menu = html_escape($_GET['count_menu']);
$count_menu = (int)$count_menu;

$order_name = [];
$one_plice = [];
$num = [];
$sub_plise = [];
$order_img = [];

//設定したカウント数でname値を書き出し配列へ入れる
for($i = 0; $i < $count_menu+1; $i++){
$order_name[$i] = html_escape($_GET['title'.$i]);
$one_plice[$i] = html_escape($_GET['plice'.$i]);
$order_img[$i] = html_escape($_GET['img'.$i]);
//文字列内にある”,”を""に変換
$one_plice[$i] = str_replace(',', '',$one_plice[$i]);
$one_plice[$i] = (int)$one_plice[$i];
$num[$i] = html_escape($_GET['num'.$i]);
$num[$i] = (int)$num[$i];
//値段と個数を掛けておく
$sub_plise[$i] = $one_plice[$i] * $num[$i];
}

追記:構成見直して改装しました

検索機能をプラスして大きく仕様を変更しました。
メニューからは1つだけ選択しsubmitで送信、注文リストorder_change.phpで要素の集計(カートの中身のようなイメージ)にしました。
下記のようなページ移行です。
menu_list.png
order_count.phpとorder_count_menu.phpの中身は同じです。Locationの飛び先だけが違います。
注文リストorder_change.phpの個数変更・削除はjsなので変更してメニュー一覧ページに飛ぶとデータは変更前に戻ってしまいます。

そこで変更データも持っていけるように、このページだけsubmitを2つに分けました。
clickイベントで合計ページに行く場合はactionをorder.phpへ、メニューに飛ぶ場合はorder_count_menu.phpへattrメソッドで切り替えです。

色々回り道をしましたが、とりあえずこの形で置いておくことにします。

GitHubにコードを公開しました

メニュー一覧のほか、管理画面、CSSなど一式をGitHubにアップしました。
宜しかったらどうぞ。

https://github.com/mugikomugi/menulist.git

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?