ファミレスのメニューもどき管理画面を作ってみた


**下記サンプルサイトは同じDBから書き出したメニュー注文ページです。**
[▶︎サンプルサイト](https://mymenu.okamechan.com/menulist/)

**下記の記事の続きです**
[▶︎ファミレスのメニューシステムもどき作ってみた](https://qiita.com/kanrek_jyosi/items/22950ac280e6bb3a5d02)

**やりたいこと**

+ DBの連携、入力、変更、削除をブラウザで操作
+ 画像アップは別フォルダへ
+ DB一覧書き出し
+ バリデーションで同じ名前と画像はアップさせない

**作成ファイル**

+ index.php(ログイン画面)
+ logout.php(ログアウト画面)
+ control_top.php(トップページと追加入力)
+ change.php(変更UPDATE)
+ change_check.php(UPDATEのバリデーション)
+ delete.php(削除)
+ db_join.php(インクルード用、DBの接続や共通で使う関数と配列を格納)
+ select_cat.php(インクルード用、formのselectパーツ)
+ select_mt.php(インクルード用、formのselectパーツ)

##管理画面のUI
jsで各操作をタブで切り替え
変更と削除はID検索で各ページにsubmitで移行。
※管理画面はDBにアクセスしてデータの変更が出来てしまう為、セキュリティーの心配もあるので一般公開は控えています。
![inputtop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641189/55e58379-9208-7a3d-6afd-a4f691094496.png)

画像は最初DBに入れるつもりでしたが、XAMPでMySQLに入れようとしたらサイズの上限に引っかかりUP不可。
なのでUP専用のディレクトリを作りデータはそっちへ、画像の名前だけDBに保存しておくことに。
数と名前を合わせておかないと後々厄介なので、入れ替え、削除のあった時は同じく連動して合わせていく仕様に設計しました。

##DBのカラムだけ配列として取得したい
![column.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641189/927f2137-ce68-9e47-3fd1-f7d8c42ab2ae.jpeg)
1列の値だけ取り出す方法が分かりませんでした。
半日かけて調べてみたところarray_column()という関数を使えば出来るのでは?
という方法に辿り着く。

```php:control_top.php
  //商品名だけ配列化
  $itemArray = array_column($data, 'item');

 ///////省略/////

 //エラー対処
  if(!check_word($item,25)){
    $err['item'] = '空文字か入力値が超えています';
  } elseif (in_array($item,$itemArray,true)) {
    //DBに同じ名前を入れさせない
    $err['item']= '同じ名の商品があります';
  } else {
    $err['item']= '';
  }
```

同じ商品名を被らせたくなかったので、DBのカラムに同じ商品名があるかチェック。
array_column(全配列の入った変数, ‘カラム名’)で商品名だけ配列化してif文で振り分け。
同じだったら省く仕組みです。

###IDのカラムも配列に
まずIDのカラム値を配列にします。
`$id_Array = array_column($data, 'ID');` 
`if(in_array($id,$id_Array))`でDBから取り出したIDと入力されたIDを照合します。

```php:change.php
//inputから持ってきたname属性値
$id = html_escape($_POST['stockid']);
//idを全角もOKにする
$id = mb_convert_kana($id, 'n', 'UTF-8');

 //DBより一覧表書き出し ID照合用
 $sql_list = 'SELECT * FROM menulist';
 $stmt = $dbh->prepare($sql_list);
 $stmt->execute();
 $data =array();
 $count = $stmt->rowCount();//レコード数取得
 //FETCH_ASSOCで配列として書き出して代入
 while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
   $data[] = $row;
 }
//IDのカラムだけ配列にする
 $id_Array = array_column($data, 'ID');

 //DBとの検索IDを照合する、DBのID以外は全て弾くので空文字やテキストのバリデーションにもなる
if(in_array($id,$id_Array,true)){
  //DBよりID書き出し
  $sql_id = "SELECT * FROM menulist WHERE id = :id";
  $stmt_id = $dbh->prepare($sql_id);
  $stmt_id->bindParam( ':id', $id, PDO::PARAM_INT);
  $stmt_id->execute();
  //配列にする
  if($stmt_id) {
    $data = $stmt_id->fetch(PDO::FETCH_ASSOC);
    }
    $item = $data['item'];
    $select_cat = $data['category'];
    $select_mt = $data['material'];
    $plice = number_format($data['plice']);
    $change_img = $data['image'];
    $submit_btn = '<input class="toBtn" type="submit" value="変更">';
} else {
    $item = '';
    $select_cat = '';
    $select_mt = '';
    $plice = '';
    $change_img = '';
    $submit_btn = '<p class="errComent">※ID欄が空かDBにないIDです。一覧に戻って選び直してください。</p>';
}
```
DBのID以外は全て弾くので空文字や数字以外のテキストのバリデーションにもなりました。

**change.php**
![cange_input.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641189/584fbdb5-23eb-61f6-5470-7b19f987c3f0.png)

##change_check.php
change_check.phpではエラーがあったらDBに入れず、入力し直しへ。
エラーがなっかたら更新して完了を表示させます。

画像の入れ替え操作は苦労しました。
変更がある場合と無い場合を想定してファイルアップの有無を0で判断し、0でなかったら新しい画像をアップし古い画像は削除。
古い画像のままだったら、古い画像を削除して同じものを入れ直します。

なのでID検索時に古い画像のファイル名も取得して運んでいきます。

```php:change_check.php
if(isset($_FILES['stockimg'])){
  $image = $_FILES['stockimg'];
  $image['name'] = html_escape($image['name']);
  //英小文字に変換
  $image['name'] = strtolower($image['name']);

  //ファイル名と拡張子を切り分けて.を除去、ピリオドを重複させない為
  $image_parts = pathinfo($image['name']);
  $extension = 'jpg';
  $image_name = $image_parts['filename'];
  $image_name = str_replace('.','',$image_name);

  if($image['size'] > 1000000){
    $err['imgsize'] = '画像が1MBを超えています';
  } elseif(file_exists('./img_up/'.$image_name.'.'.$extension) === TRUE) {
    //file_exists関数でディレクトリ内を調べて、同じファイル名があった場合はアップさせない
    $err['imgsize'] = '同名のファイルがあります。違うファイル名にしてください。';
  } else {
    $err['imgsize'] = '';
  }
}
 ///////省略/////

//エラーが無かったら更新へ
if($err['item']== '' && $err['imgsize'] == '' && $err['plice']== ''){
//ファイルアップがあった時の対処、0じゃなっかたらディレクトリにアップ、ここは苦労した
  if((int)$image_name !== 0){
    move_uploaded_file($image['tmp_name'],'./img_up/'.$image_name.'.'.$extension);
    //画像が変更されたら古い画像はフォルダより削除
    unlink('./img_up/'.$old_img);
    //DBに持っていくファイル名
    $image = $image_name.'.'.$extension;
    //見本表示
    $prev_img = '<p class="center">変更画像<br><img class="thumb12" src="'.$img_path.$image_name.'.'.$extension.'" alt=""></p>';
  } else {
    //DBに持っていくファイル名を置かないとDBからファイル名が消えてしまう
    $image = $old_img;
    $prev_img = '<p>変更画像無し</p>';
  }
```

ファイルアップは前にプチ・クラウドストレージを作ったので、ベースはそこから引用してきました。
[▶︎プチ・クラウドストレージ作ってみた](https://qiita.com/kanrek_jyosi/items/ffbeab1ce30da87832ab)

delete.phpもchange_check.phpとほぼ同じ作りです。

管理画面は注文ページより、ほぼ思うように作れました。
期間は2週間+α、かかりました。

##作り終えて振り返り
調べていくとDB接続の書き方も人によりマチマチで「この方法知らない…」ということも多々遭遇。
関数、条件の立て方も同様で、長いと頭がクラクラしてきます。

システム構築の実務経験がないので、使う人の行動を想像しながら作りましたが
実務があったら、もっと配慮ができる設計が出来たのかなとも思っています。

##以下サンプルコードです
より実用的なコードに近づけるようご意見いただけると嬉しいです。

<details><summary>サンプルコード</summary><div>
・index.php(ログイン画面)
・logout.php(ログアウト画面)
・db_join.php(インクルード用、DBの接続や共通で使う関数と配列を格納)
・select_cat.php(インクルード用、formのselectパーツ)
・select_mt.php(インクルード用、formのselectパーツ)
上記５個のファイルは省略します。

```php:control_top.php
<?php
//ログインしていないとアクセスさせない
session_start();
session_regenerate_id(true);
if(isset($_SESSION['login']) === false){
    header('Location: index.php');
    exit();
}

try{
  include_once(dirname(__FILE__).'/db_join.php');
  //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;//FETCH_ASSOCで配列として書き出して代入
  }

  //DBのカラムに同じ商品名があるかチェック
  //商品名だけ配列化
  $itemArray = array_column($data, 'item');

$item = '';
$category='';
$material = '';
$plice = '';
$err = ['item'=>'','cat'=>'','mat'=>'','plice'=>'','imgsize'=>''];
$dberr = '';

if($_SERVER['REQUEST_METHOD'] === 'POST'){

  $item = html_escape($_POST['stock']);
  $category = html_escape($_POST['category']);
  $material = html_escape($_POST['material']);
  $plice = html_escape($_POST['stockplice']);
  $plice = mb_convert_kana($plice, 'n', 'UTF-8');
  $image = $_FILES['stockimg'];
  $image['name'] = html_escape($image['name']);
  //英小文字に変換
  $image['name'] = strtolower($image['name']);
  $plice = strtolower($plice);

  //ファイル名と拡張子を切り分けて.を除去、ピリオドを重複させない為
  $image_parts = pathinfo($image['name']);
  //$extension = $image_parts['extension'];
  $extension = 'jpg';
  $image_name = $image_parts['filename'];
  $image_name = str_replace('.','',$image_name);
  //base64でencode追加
  $image_name = base64_encode($image_name);

  //エラー対処
  if(!check_word($item,25)){
    $err['item'] = '空文字か入力値が超えています';
  } elseif (in_array($item,$itemArray,true)) {
    //DBに同じ名前を入れさせない
    $err['item']= '同じ名の商品があります';
  } else {
    $err['item']= '';
  }
  if($category === ''){
    $err['cat'] = '選択してください';
  } else {
    $err['cat']= '';
  }
  if($material === ''){
    $err['mat'] = '選択してください';
  } else {
    $err['mat']= '';
  }
  if(!check_word($plice,8)){
    $err['plice'] = '空文字か入力値が超えています';
  } else {
    $err['plice']= '';
  }
  if($image['size'] > 1000000 && $image['size'] == 0){
    $err['imgsize'] = '画像が選択されていないかサイズが1MBを超えています';
  } elseif(file_exists('./img_up/'.$image_name.'.'.$extension) === TRUE) {
    //file_exists関数でディレクトリ内を調べて、同じファイル名があった場合はアップさせない
    $err['imgsize'] = '同名のファイルがあります。違うファイル名にしてください。';
  } else {
    $err['imgsize'] = '';
  }

//empty($err)ではダメで下の書き方でtrueになった
  if($err['item']== '' && $err['cat']== '' && $err['mat']== '' && $err['imgsize'] == '' && $err['plice']== ''){
    //デコードして画像アップ
    $image_name = base64_decode($image_name);
    move_uploaded_file($image['tmp_name'],'./img_up/'.$image_name.'.'.$extension);
    $dberr = '<img class="thumb" src="'.$img_path.$image_name.'.'.$extension.'" alt="">商品「'.$item.'」は正常にUPされました';

  //DBに入力データを入れる
  $sql = "INSERT INTO menulist(item,image,category,material,plice) VALUE(:item,:image,:category,:material,:plice)";
  $stmt_in = $dbh->prepare($sql);
  $stmt_in->bindValue(':item',$item,PDO::PARAM_STR);
  //DBには画像ファイル名のみUP
  $stmt_in->bindValue(':image',$image_name.'.'.$extension,PDO::PARAM_STR);
  $stmt_in->bindValue(':category',$category,PDO::PARAM_STR);
  $stmt_in->bindValue(':material',$material,PDO::PARAM_STR);
  $stmt_in->bindValue(':plice',$plice,PDO::PARAM_INT);
  $stmt_in->execute();
  }
//再読み込みを防ぐ為、同ページだけど飛ばす
  header('Location:/menulist/control/control_top.php');
}

} catch (PDOException $e){
  print($e->getMessage());
  die();
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DBテスト管理画面</title>
  <link rel="stylesheet" href="/menulist/common/sanitize.css">
  <link rel="stylesheet" href="/menulist/common/style.css">
  <link rel="stylesheet" href="/menulist/common/control.css">
  <!--ファビコン32x32-->
  <link rel="shortcut icon" href="/menulist/favicon.ico" type="image/vnd.microsoft.icon">
</head>
<body>
  <div id="wrapper">
    <header id="header">
      <p id="logout"><a href="logout.php">ログアウト</a></p>
      <h1 class="topTitle">DBテスト管理画面</h1>
      <p class="center notice1">入力の場合IDの設定は不要、金額は数値のみで<br>ブラウザの再読み込みはしないでください。エラーになります。</p>
      <p class="center notice2">IDで商品を検索してください</p>
    </header>

    <main id="main">
      <ul class="formChange">
        <li data-id="insart" class="act">入力</li>
        <li data-id="update">変更</li>
        <li data-id="deleteForm">削除</li>
      </ul>

      <!-- 追加入力 -->
      <form class="changeBox" id="insart" method="post" action="" enctype="multipart/form-data">
        <div class="formLow">
          <div class="stockId">
            <p>ID</p>
            <p class="formInput">-</p>
          </div>
          <div class="stock">
            <label>商品名</label>
            <input type="text" name="stock">
            <p><?php echo $err['item']; ?></p>
          </div>
          <div class="stockCategory">
            <label>カテゴリー</label>
            <select name="category">
              <option value="" selected="selected">選択する</option>
              <!-- selectはインクルード -->
              <?php include_once(dirname(__FILE__).'/select_cat.php'); ?>

            </select>
            <p><?php echo $err['cat']; ?></p>
          </div>
          <div class="materialForm">
            <label>素材</label>
            <select name="material">
                <option value="" selected="selected">選択する</option>
                <!-- selectはインクルード -->
                <?php include_once(dirname(__FILE__).'/select_mt.php'); ?>

            </select>
            <p><?php echo $err['mat']; ?></p>
          </div>
          <div class="stockplice">
            <label>金額</label>
            <input type="text" name="stockplice">
            <p><?php echo $err['plice']; ?></p>
          </div>
        </div>
        <!-- //.formLow -->
        <div class="center">
          <label>商品画像:サイズ横640px縦420px</label><br>
          <input type="file" name="stockimg">
          <p><?php echo $err['imgsize']; ?></p>
          <?php echo $dberr; ?>
        </div>
        <input class="toBtn" type="submit" value="追加">
      </form>
      <!-- //#insartBox -->

      <!-- 変更入力 -->
      <!-- 検索 -->
      <div id="update" class="changeBox">
        <form method="post" action="/menulist/control/change.php">
          <div class="formLow">
            <label class="sarchId">ID</label>
            <input class="inputId" type="text" name="stockid">
          </div>
          <input class="toBtn" type="submit" value="検索">
        </form>
      </div>
      <!-- //#updateId -->

      <!-- 削除 -->
      <div id="deleteForm" class="changeBox">
        <form method="post" action="/menulist/control/delete.php">
          <div class="formLow">
            <label class="sarchId">ID</label>
            <input class="inputId" type="text" name="stockid">
          </div>
          <input class="toBtn" type="submit" value="検索">
        </form>

      </div>
      <!-- //#deleteForm -->

      <!-- メニュー一覧データ -->
      <div class="stockBox">
        <!-- カテゴリー絞り込みタグ -->
        <ul class="topNav">
        <?php for($i = 0; $i < count($cat_list); $i++): ?>
          <li id="<?php echo 'cat_select_'.$i; ?>"><?php echo $cat_list[$i]; ?></li>
        <?php endfor; ?>
        <li id="all">ALL</li>
        </ul>
        <p class="totalStock"><span>全登録数</span><?php echo $count; ?>項目</p>
        <p id="catShow"></p>
        <table id="stockList">
          <tr>
            <th class="stocklistId">ID</th><th class="stocklist">商品名</th><th class="stockImg">商品画像</th><th class="stocklisutoCat">カテゴリー</th><th class="stocklistMat">素材</th><th class="stocklistPlice">金額</th>
          </tr>
          <!-- foreachの外にforで囲み、カテゴリー数をループ -->
          <!-- foreachの中に$cat_list[$i]を入れるとエラーになる -->
          <?php for($i = 0; $i < count($cat_list); $i++): ?>
            <?php 
              $cat_item = $cat_list[$i];
              $cat_select = 'cat_select_'.$i;
               ?>
            <?php foreach($data as $row): ?>
              <?php if($row['category'] == $cat_item): ?>
              <tr class="<?php echo $cat_select; ?>">
                <td class="stocklistId"><?php echo $row['ID']; ?></td>
                <td class="stocklist"><?php echo $row['item']; ?></td>
                <td class="stockImg"><img src="<?php echo $img_path.$row['image']; ?>" alt=""></td>
                <td class="stocklisutoCat"><?php echo $row['category']; ?></td>
                <td class="stocklistMat"><?php echo $row['material']; ?></td>
                <td class="stocklistPlice"><?php echo number_format($row['plice']); ?>円</td>
              </tr>
              <?php endif; ?>
            <?php endforeach; ?>
          <?php endfor; ?>

        </table>
      </div>
      <!-- //.stockBox -->
    </main>

    <footer id="footer">
      <small>DBテストメニューsystem</small>
    </footer>
  </div>
  <!-- //# wrapper-->
  <script src="/menulist/common/jquery-3.6.0.min.js"></script>
  <script src="/menulist/common/control.js"></script>
</body>
</html>
```

```php:change.php
<?php
//ログインしていないとアクセスさせない
session_start();
session_regenerate_id(true);
if(isset($_SESSION['login']) === false){
    header('Location: index.php');
    exit();
}

try {
include_once(dirname(__FILE__).'/db_join.php');

$id = html_escape($_POST['stockid']);
//idを全角もOKにする
$id = mb_convert_kana($id, 'n', 'UTF-8');

 //DBより一覧表書き出し ID照合用
 $sql_list = 'SELECT * FROM menulist';
 $stmt = $dbh->prepare($sql_list);
 $stmt->execute();
 $data =array();
 $count = $stmt->rowCount();//レコード数取得
 //FETCH_ASSOCで配列として書き出して代入
 while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
   $data[] = $row;
 }
//IDのカラムだけ配列にする
 $id_Array = array_column($data, 'ID');

 //DBとの検索IDを照合する、DBのID以外は全て弾くので空文字やテキストのバリデーションにもなる
if(in_array($id,$id_Array)){
  //DBよりID書き出し
  $sql_id = "SELECT * FROM menulist WHERE id = :id";
  $stmt_id = $dbh->prepare($sql_id);
  $stmt_id->bindParam( ':id', $id, PDO::PARAM_INT);
  $stmt_id->execute();
  //配列にする
  if($stmt_id) {
    $data = $stmt_id->fetch(PDO::FETCH_ASSOC);
    }
    $item = $data['item'];
    $select_cat = $data['category'];
    $select_mt = $data['material'];
    $plice = number_format($data['plice']);
    $change_img = $data['image'];
    $submit_btn = '<input class="toBtn" type="submit" value="変更">';
} else {
    $item = '';
    $select_cat = '';
    $select_mt = '';
    $plice = '';
    $change_img = '';
    $submit_btn = '<p class="errComent">※ID欄が空かDBにないIDです。一覧に戻って選び直してください。</p>';
}
  
} catch (PDOException $e){
  print($e->getMessage());
  die();
}

?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DBテスト管理画面・変更</title>
  <link rel="stylesheet" href="/menulist/common/sanitize.css">
  <link rel="stylesheet" href="/menulist/common/style.css">
  <link rel="stylesheet" href="/menulist/common/control.css">
  <!--ファビコン32x32-->
  <link rel="shortcut icon" href="/menulist/favicon.ico" type="image/vnd.microsoft.icon">
</head>
<body>
  <div id="wrapper">
    <header id="header">
      <h1 class="topTitle">DBテスト管理画面・変更</h1>
      <p class="center notice1">変更箇所のみ書き換えてください</p>
    </header>

    <main id="main">
      <!-- 変更 -->
      <form method="post" action="change_check.php" enctype="multipart/form-data">
        <div class="formLow">
          <div class="stockId">
            <p>ID</p>
            <p class="formInput"><?php echo $id; ?></p>
            <input type="hidden" name="stockid" value="<?php echo $id; ?>">
          </div>
          <div class="stock">
            <label>商品名</label>
            <input type="text" name="stock" value="<?php echo $item; ?>">
          </div>
          <div class="stockCategory">
            <label>カテゴリー</label>
            <select name="category" value="<?php echo $select_cat; ?>">
            <!-- selectはインクルード -->
            <?php include_once(dirname(__FILE__).'/select_cat.php'); ?>
            </select>
          </div>

          <div class="materialForm">
            <label>素材</label>
            <select name="material" value="<?php echo $select_mt; ?>">
            <!-- selectはインクルード -->
            <?php include_once(dirname(__FILE__).'/select_mt.php'); ?>
            </select>
          </div>

          <div class="stockplice">
            <label>金額</label>
            <input type="text" name="stockplice" value="<?php echo $plice; ?>">
          </div>
        </div>
        <!-- //.formLow -->
        <div class="center">
          <label>商品画像:サイズ横640px縦420px<br><span class="text12">※変更のある場合のみUP</span></label><br>
          <input type="file" name="stockimg">
          <p class="center">
            <img class="thumb12" src="<?php echo $img_path.$change_img; ?>" alt="">
            <!-- 削除のある場合に古い画像も持っていく -->
            <input type="hidden" name="old_img" value="<?php echo $change_img; ?>">
          </p>
          <p class="text12 center mg0">変更前の画像です</p>
        </div>
        <?php echo $submit_btn; ?>
      </form>
      <div id="toList"><a href="/menulist/control/control_top.php">管理画面トップへ</a></div>
  </main>

<footer id="footer">
  <small>DBテストメニューsystem</small>
</footer>
</div>
<!-- //# wrapper-->
<script src="/menulist/common/jquery-3.6.0.min.js"></script>
<script src="/menulist/common/control.js"></script>
</body>
</html>
```

```php:change_check.php
<?php
//ログインしていないとアクセスさせない
session_start();
session_regenerate_id(true);
if(isset($_SESSION['login']) === false){
    header('Location: index.php');
    exit();
}

try {
include_once(dirname(__FILE__).'/db_join.php');

$err = ['item'=>'','plice'=>'','imgsize'=>''];

$id = html_escape($_POST['stockid']);
$item = html_escape($_POST['stock']);
$category = html_escape($_POST['category']);
$material = html_escape($_POST['material']);
$plice = html_escape($_POST['stockplice']);
$plice = mb_convert_kana($plice, 'n', 'UTF-8');
$old_img = html_escape($_POST['old_img']);

if(isset($_FILES['stockimg'])){
  $image = $_FILES['stockimg'];
  $image['name'] = html_escape($image['name']);
  //英小文字に変換
  $image['name'] = strtolower($image['name']);

  //ファイル名と拡張子を切り分けて.を除去、ピリオドを重複させない為
  $image_parts = pathinfo($image['name']);
  $extension = 'jpg';
  $image_name = $image_parts['filename'];
  $image_name = str_replace('.','',$image_name);

  if($image['size'] > 1000000){
    $err['imgsize'] = '画像が1MBを超えています';
  } elseif(file_exists('./img_up/'.$image_name.'.'.$extension) === TRUE) {
    //file_exists関数でディレクトリ内を調べて、同じファイル名があった場合はアップさせない
    $err['imgsize'] = '同名のファイルがあります。違うファイル名にしてください。';
  } else {
    $err['imgsize'] = '';
  }
}

//var_dump(is_number($plice));
  //エラー対処
  if(!check_word($item,25)){
    $err['item'] = '空文字か入力値が超えています';
  } else {
    $err['item']= '';
  }

  if(!check_word($plice,8)){
    $err['plice'] = '空文字か入力値が超えています';
  } elseif(is_numeric($plice) == FALSE) {
    //金額が数字じゃなかったらNG
    $err['plice'] = '数字を入力してください';
    //金額変更でNGが出ると下記の変数に値が無くなるので対処
    $prev_img = '';
  } else {
    $err['plice']= '';
    $plice = number_format($plice);
  }

//エラーが無かったら更新へ
if($err['item']== '' && $err['imgsize'] == '' && $err['plice']== ''){
//ファイルアップがあった時の対処、0じゃなっかたらディレクトリにアップ、ここは苦労した
  if((int)$image_name !== 0){
move_uploaded_file($image['tmp_name'],'./img_up/'.$image_name.'.'.$extension);
    //画像が変更されたら古い画像はフォルダより削除
    unlink('./img_up/'.$old_img);
    //DBに持っていくファイル名
    $image = $image_name.'.'.$extension;
    //見本表示
    $prev_img = '<p class="center">変更画像<br><img class="thumb12" src="'.$img_path.$image_name.'.'.$extension.'" alt=""></p>';
  } else {
    //DBに持っていくファイル名を置かないとDBからファイル名が消えてしまう
    $image = $old_img;
    $prev_img = '<p>変更画像無し</p>';
  }

  //指定のidのDBを更新
  $sql_up = 'UPDATE menulist SET item=:item,image=:image,category=:category,material=:material,plice=:plice WHERE id = :id';
  $stmt_up = $dbh->prepare($sql_up);
  $stmt_up->bindParam( ':id', $id, PDO::PARAM_INT);
  $stmt_up->bindValue(':item',$item,PDO::PARAM_STR);
  $stmt_up->bindValue(':image',$image,PDO::PARAM_STR);
  $stmt_up->bindValue(':category',$category,PDO::PARAM_STR);
  $stmt_up->bindValue(':material',$material,PDO::PARAM_STR);
  $stmt_up->bindValue(':plice',$plice,PDO::PARAM_INT);
  $stmt_up->execute();

  $notice = '以下の内容で更新しました';
  $back_btn = '<div id="toList"><a href="/menulist/control/control_top.php">管理画面トップへ</a></div>';
} else {
  $notice = 'エラーがあります。戻って修正してください。';
  //お手軽にhistory.back使いましたが「フォーム再送信の確認」が出る可能性有り
  //かといってa hrefだと入力値が消える。手間だけどもう一つ入力値を持っていった再入力用ページを作る?
  $back_btn = '<div id="toList"><a onclick="history.back()">修正する</a></div>';
}

} catch (PDOException $e){
  print($e->getMessage());
  die();
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DBテスト管理画面・変更確認</title>
  <link rel="stylesheet" href="/menulist/common/sanitize.css">
  <link rel="stylesheet" href="/menulist/common/style.css">
  <link rel="stylesheet" href="/menulist/common/control.css">
  <!--ファビコン32x32-->
  <link rel="shortcut icon" href="/menulist/favicon.ico" type="image/vnd.microsoft.icon">
</head>
<body>
  <div id="wrapper">
    <header id="header">
      <h1 class="topTitle">DBテスト管理画面・変更確認</h1>
      <p class="center notice1"><?php echo $notice; ?></p>
    </header>

    <main id="main">
      <div class="formLow">
          <div class="stockId">
            <p>ID</p>
            <p class="formInput"><?php echo $id; ?></p>
          </div>
          <div class="stock">
            <label>商品名</label>
            <p class="formInput"><?php echo $item; ?></p>
            <p><?php echo $err['item']; ?></p>
          </div>
          <div class="stockCategory">
            <label>カテゴリー</label>
            <p class="formInput"><?php echo $category; ?></p>
          </div>
          <div class="materialForm">
            <label>素材</label>
            <p class="formInput"><?php echo $material; ?></p>
          </div>

          <div class="stockplice">
            <label>金額</label>
            <p class="formInput"><?php echo $plice; ?></p>
            <p><?php echo $err['plice']; ?></p>
          </div>
        </div>
        <!-- //.formLow -->
        <div class="center">
          <?php echo $prev_img; ?>
          <p class="center"><?php echo $err['imgsize']; ?></p>
        </div>

      <?php echo $back_btn; ?>
    </main>
  </div>
  <!-- //#wrapper -->
<footer id="footer">
  <small>DBテストメニューsystem</small>
</footer>
</div>
<!-- //# wrapper-->
<script src="/menulist/common/jquery-3.6.0.min.js"></script>
<script src="/menulist/common/control.js"></script>
</body>
</html>
```

```php:delete.php
<?php
//ログインしていないとアクセスさせない
session_start();
session_regenerate_id(true);
if(isset($_SESSION['login']) === false){
    header('Location: index.php');
    exit();
}

try {
  include_once(dirname(__FILE__).'/db_join.php');

  $id = html_escape($_POST['stockid']);
  $id = mb_convert_kana($id, 'n', 'UTF-8');

  //DBより一覧表書き出し ID照合用
  $sql_list = 'SELECT * FROM menulist';
  $stmt = $dbh->prepare($sql_list);
  $stmt->execute();
  $data =array();
  $count = $stmt->rowCount();//レコード数取得
  while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $data[] = $row;//FETCH_ASSOCで配列として書き出して代入
  }
  //IDのカラムだけ配列にする
  $id_Array = array_column($data, 'ID');

  //DBとの検索IDを照合する
  if(in_array($id,$id_Array)){
    $sql_id = "SELECT * FROM menulist WHERE id = :id";
    $stmt_id = $dbh->prepare($sql_id);
    $stmt_id->bindParam(':id', $id, PDO::PARAM_INT);
    $stmt_id->execute();
    //配列にする
    if($stmt_id) {
      $data = $stmt_id->fetch(PDO::FETCH_ASSOC);
    }
    
    $item = $data['item'];
    $plice = number_format($data['plice']);
    $select_cat = $data['category'];
    $select_mt = $data['material'];
    $change_img = $data['image'];
    $submit_btn = '<input class="toBtn" type="submit" value="削除">';
  } else {
    $item = '';
    $select_cat = '';
    $select_mt = '';
    $plice = '';
    $change_img = '';
    $submit_btn = '<p class="errComent">※DBにないIDです。一覧に戻って選び直してください。</p>';
  }

  if($_SERVER['REQUEST_METHOD'] === 'POST'){
    //isset置かないとNoticeが出る
    if(isset($_POST['deleteid'])){
      $id = html_escape($_POST['deleteid']);
      $image = html_escape($_POST['deleteimg']);

      //DBより削除
      $sql_delete = "DELETE FROM menulist WHERE id = :id";
      $stmt_delete = $dbh->prepare($sql_delete);
      $stmt_delete->bindParam( ':id', $id, PDO::PARAM_INT);
      $stmt_delete->execute();

      //画像フォルダからも削除
      unlink('./img_up/'.$image);
      //実行されたらトップに飛ばす
      header('Location:/menulist/control/control_top.php');
    }
  }

} catch (PDOException $e){
  print($e->getMessage());
  die();
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DBテスト管理画面・変更</title>
  <link rel="stylesheet" href="/menulist/common/sanitize.css">
  <link rel="stylesheet" href="/menulist/common/style.css">
  <link rel="stylesheet" href="/menulist/common/control.css">
  <!--ファビコン32x32-->
  <link rel="shortcut icon" href="/menulist/favicon.ico" type="image/vnd.microsoft.icon">
</head>
<body>
  <div id="wrapper">
    <header id="header">
      <h1 class="topTitle">DBテスト管理画面・削除</h1>
      <p class="center notice1">以下のメニューを削除します</p>
    </header>

    <main id="main">
      <!-- 変更 -->
      <form method="post" action="">
          <div class="stockBox">
            <table>
              <tr>
                <th>ID</th><th>商品名</th><th>商品画像</th><th>カテゴリー</th><th>素材</th><th>金額</th>
              </tr>
              <tr>
                <td class="stocklistId"><?php echo $id; ?><input type="hidden" name="deleteid" value="<?php echo $id; ?>"></td>
                <td class="stocklist"><?php echo $item; ?></td>
                <td class="stockImg"><img src="<?php echo $img_path.$change_img; ?>" alt=""><input type="hidden" name="deleteimg" value="<?php echo $change_img; ?>"></td>
                <td class="stocklisutoCat"><?php echo $select_cat; ?></td>
                <td class="stocklistMat"><?php echo $select_mt; ?></td>
                <td class="stocklistPlice"><?php echo $plice ; ?>円</td>
              </tr>
            </table>
          </div>
          <?php echo $submit_btn; ?>
        </form>
      <div id="toList"><a href="/menulist/control/control_top.php">管理画面トップへ</a></div>
  </main>

<footer id="footer">
  <small>DBテストメニューsystem</small>
</footer>
</div>
<!-- //# wrapper-->
<script src="/menulist/common/jquery-3.6.0.min.js"></script>
<script src="/menulist/common/control.js"></script>
</body>
</html>
```

</div></details>