【HTML & PHP】在庫管理システム④在庫情報編集画面を作ろう

PHP HTML5

今回は在庫管理システムを作る事を目指して、在庫一覧に登録したデータを編集・削除する画面を作ろうと思います。
(こちらの記事の続きとなっています。)

データベース上のテーブルを操作する必要がありますので、xamppのMySQLを起動しておきます。
以前に起動する方法を記事にしているので、こちらもご参照ください。

在庫一覧画面に表示する内容を増やす

前回の記事では、商品名と画像しか表示しなかったので、今回は表示する情報を増やしたいと思います。

<?php
session_start();
if( !isset( $_SESSION['login_flg'] ) ) {
    print 'ログインしてください。<a href="index.html">ログイン</a>';
    exit();
}
/* 外部ファイル読み込み */
require_once('common/common.php');
/* データベース関係の処理 */
get_database_data($dsn,$user,$password);
$dbh = new PDO($dsn,$user,$password);
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
?>

<!DOCTYPE html>

<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>在庫管理システム在庫一覧</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php
/* 在庫一覧表示処理 */
    $sql = 'SELECT * FROM goods WHERE 1';
    $godds_stmt=$dbh->prepare($sql);
    $godds_stmt->execute();
    while(true)
    {
        $goods_rec = $godds_stmt->fetch(PDO::FETCH_ASSOC);
        if($goods_rec==false) break;
        print '<figure class="thumbnail"><input type="hidden" id="thumbnail'.$goods_rec['code'].'" name="thumbnail'.$goods_rec['code'].'" value="'.$goods_rec['code'].'">'
                                       .'<img src="./image/'.$goods_rec['Image'].'" height="200px", width="200px">'
                                       .'<table>'
                                       .'<tr><td>商品名</td><td>:'.$goods_rec['GoodsName'].'</td></tr>'
                                       .'<tr><td>仕入先</td><td>:'.$goods_rec['Supplier'].'</td></tr>'
                                       .'<tr><td>仕入価格</td><td>:'.$goods_rec['PurchasePrice'].'円</td></tr>'
                                       .'<tr><td>販売価格</td><td>:'.$goods_rec['Price'].'円</td></tr>'
                                       .'<tr><td>在庫数</td><td>:'.$goods_rec['Inventory'].'</td></tr>'
                                       .'<tr><td>保管場所</td><td>:'.$goods_rec['Place'].'</td></tr>'
                                       .'</table>'
             .'</figure>';
    }
?>
<script>
document.addEventListener('DOMContentLoaded',function(){
    const thumbnails = document.querySelectorAll('.thumbnail');
    for(var i = 0; i < thumbnails.length; i++){
        thumbnails[i].addEventListener('click',function(){
            const firstChild = this.firstElementChild;
            location.href = 'NewItemAdd.html?code='+firstChild.value;
        },false);
    }
},false);
</script>
    <hr>
    <p><input type="button" onclick="location.href='MainMenu.html'"   value="メインメニュー"></p>
    <p><input type="button" onclick="location.href='NewItemAdd.html'" value="新規在庫登録"></p>
    <p><input type="button" onclick="location.href='ItemList.html'"   value="在庫情報一覧"></p>
</body>
</html>

データベース上のテーブルの情報を、すべて画面に表示するように修正しています。

<input type=”hidden”~のコードは、在庫情報削除機能と在庫情報修正機能を実装するために追加しました。

<script>~は、classがthumbnailの要素(商品画像や商品名等)をクリックしたときに、その在庫情報を修正する画面を表示するために追加しています。(後に記述しますが、在庫情報修正画面で、修正か削除を選択できるようにしました。)

このスクリプトが動作すると、NewItemAdd.htmlを表示する際に、クエリパラメータ ?code=○○を設定します。(○○はclassがthumbnailの1番目の子要素のvalue。つまり、<input type=”hidden”~のvalue。)

在庫一覧画面(修正後)

在庫情報修正画面

在庫情報を登録後に誤りがあった場合は、修正できるように在庫情報修正画面が必要です。
基本的に、在庫登録画面と同じように表示しようと思います。
ただし、各入力欄には、前回登録した情報を入れておくとユーザは楽でしょう。
新しくhtmlファイルを作成するのもいいですが、在庫登録画面(NewItemAdd.html)を改造して、新規登録と情報修正のどちらも同じファイルで済むようにしたいと思います。

在庫情報修正画面のコード(NewItemAdd.html)

新規登録と情報修正のどちらにも対応させたコードを下記に記載します。

<?php
session_start();
if( !isset( $_SESSION['login_flg'] ) ) {
    print 'ログインしてください。<a href="index.html">ログイン</a>';
    exit();
}
/* 外部ファイル読み込み */
require_once('common/common.php');
/* データベース関係の処理 */
get_database_data($dsn,$user,$password);
$dbh = new PDO($dsn,$user,$password);
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
/* クエリがあれば、現テーブルデータを読み出す */
if(isset($_GET['code'])==true){
    $sql = 'SELECT * FROM goods WHERE code='.$_GET['code'];
    $godds_stmt=$dbh->prepare($sql);
    $godds_stmt->execute();
    $goods_rec = $godds_stmt->fetch(PDO::FETCH_ASSOC);
    if($goods_rec==false)
        unset($goods_rec);
}
?>

<!DOCTYPE html>

<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex" />
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>在庫管理システム新規在庫登録</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
<?php
if(isset($goods_rec)==true){
    print'<h1>在庫情報更新画面</h1>';
}
?>
    <form method="post" action="NewItemAdd_check.php" enctype="multipart/form-data">
        <p>登録日<input type="date" name="Add_date" value='<?=date('Y-m-d')?>'  readonly></p>
        <p>★商品名<input type="text" name="GoodsName" required></p>
        <p>仕入先(URL)<input type="url" name="Supplier"></p>
        <p>仕入価格<input type="number" name="PurchasePrice" min="0" value="0">円</p>
        <p>販売価格<input type="number" name="Price" min="0" value="0">円</p>
        <p>在庫数<input type="number" name="Inventory" min="0" value="0"></p>
        <p>保管場所<input type="text" name="Place"></p>
        <p>画像<input type="file" name="upload_file" accept="image/*"></p>
<?php
if(isset($goods_rec)==true){
    print'<p><b>↑画像を変更しない場合</b>は、ファイルを選択しないでください。</p>';
    print'<p><img src="./image/'.$goods_rec['Image'].'" height="100px", width="100px"></p>';
    print'<p><input type="hidden" name="code" value="'.$goods_rec['code'].'"></p>';
}
?>
        <p>★は入力必須項目</p>
        <p><input type="submit" value="登録">
<?php
if(isset($goods_rec)==true){
    print'<input type="button" onclick="location.href=\'ItemDelete.php?code='.$goods_rec['code'].'\'"   value="削除">';
}
?>
        </p>
    </form>
    <hr>
    <p><input type="button" onclick="location.href='MainMenu.html'"   value="メインメニュー"></p>
    <p><input type="button" onclick="location.href='NewItemAdd.html'" value="新規在庫登録"></p>
    <p><input type="button" onclick="location.href='ItemList.html'"   value="在庫情報一覧"></p>
<script>
<?php
    if(isset($goods_rec)==true){
        print 'var element = document.querySelector(\'input[name="Add_date"]\');';
        print 'element.value = "'.$goods_rec['Add_date'].'";';
        print 'element = document.querySelector(\'input[name="GoodsName"]\');';
        print 'element.value = "'.$goods_rec['GoodsName'].'";';
        print 'element = document.querySelector(\'input[name="Supplier"]\');';
        print 'element.value = "'.$goods_rec['Supplier'].'";';
        print 'element = document.querySelector(\'input[name="PurchasePrice"]\');';
        print 'element.value = "'.$goods_rec['PurchasePrice'].'";';
        print 'element = document.querySelector(\'input[name="Price"]\');';
        print 'element.value = "'.$goods_rec['Price'].'";';
        print 'element = document.querySelector(\'input[name="Inventory"]\');';
        print 'element.value = "'.$goods_rec['Inventory'].'";';
        print 'element = document.querySelector(\'input[name="Place"]\');';
        print 'element.value = "'.$goods_rec['Place'].'";';
    }
?>
</script>
</body>
</html>

クエリパラメータに$_GET[‘code’]があれば、テーブルで対象のレコードを読み込み、レコードがあれば、「在庫情報更新画面ですよ」をユーザに認識してもらうために、在庫情報更新画面という文字を表示します。また、現在サムネイルとして表示している画像を画面に表示します。

現在編集中のレコード情報を<script>~で各入力欄に設定しています。
<script>~は、新規在庫情報登録時(=$_GET[‘code’]が無い時)はhtmlファイルに書かないようにしています。

在庫情報更新画面表示中は、削除ボタンを表示して、修正情報を登録するか削除するか選択できるようにしています。

在庫情報編集画面

テーブルに修正情報を反映する

テーブルに登録した情報を読み出して修正画面を表示し、登録または削除を選択できるようにしたので、まずは修正情報を登録するコードを作成します。

<?php
session_start();
if( !isset( $_SESSION['login_flg'] ) ) {
    print 'ログインしてください。<a href="index.html">ログイン</a>';
    exit();
}
try{
/* 外部ファイル読み込み */
    require_once('common/common.php');
/* 内部関数定義 */
    /* POSTデータのサニタイズ */
    function sanitizing($in_data){
        foreach($in_data as $key=>$value){
            $out_data[$key]=htmlspecialchars($value,ENT_QUOTES,'UTF-8');
        }
        return($out_data);
    }
    /* データベース関係の処理 */
    get_database_data($dsn,$user,$password);
    $dbh = new PDO($dsn,$user,$password);
    $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    /* POSTデータのサニタイズ化 */
    $post=sanitizing($_POST);
    if(isset($post['code'])==false){
    /* 新規在庫登録処理 */
        /* 商品名が空ではない? */
        if(!empty($post['GoodsName'])){
            /* 添付ファイルを処理する */
            $temp_file_name_org = '';
            if(is_uploaded_file($_FILES['upload_file']['tmp_name'])){
                $finfo = new finfo(FILEINFO_MIME_TYPE);
                $mime_type = $finfo->file($_FILES['upload_file']['tmp_name']);
                $res = finfo_close($finfo);
                /* getimagesize関数で画像情報を取得する */
                list($img_width, $img_height, $mime_type, $attr) = getimagesize($_FILES['upload_file']['tmp_name']);
                switch($mime_type){
                    /* jpegの場合 */
                    case IMAGETYPE_JPEG:
                        $img_extension = "jpg";
                        break;
                    /* pngの場合 */
                    case IMAGETYPE_PNG:
                        $img_extension = "png";
                        break;
                    /* gifの場合 */
                    case IMAGETYPE_GIF:
                        $img_extension = "gif";
                        break;
                }
                /* 拡張子が画像だったか? */
                if(isset($img_extension)){
                    /* ファイルのアップロード */
                    $temp_file_name_org = $post['GoodsName'].'_'.date('YmdHis').'.'.$img_extension ;
                    $temp_file_name     = './image/'.$temp_file_name_org ;
                    move_uploaded_file($_FILES['upload_file']['tmp_name'], $temp_file_name);
                }
            }
            /* POSTデータをデータベースに登録処理 */
            $sql = 'INSERT INTO goods (GoodsName, Add_date, Supplier, PurchasePrice, Price, Inventory, Place, Image) VALUES ("'.$post['GoodsName'].    '","'
                                                                                                                               .$post['Add_date'].     '","'
                                                                                                                               .$post['Supplier'].     '","'
                                                                                                                               .$post['PurchasePrice'].'","'
                                                                                                                               .$post['Price'].        '","'
                                                                                                                               .$post['Inventory'].    '","'
                                                                                                                               .$post['Place'].        '","'
                                                                                                                               .$temp_file_name_org.   '");';
            $result=$dbh->query($sql);
        }
        /* 新規在庫登録画面を表示する */
        header('Location:NewItemAdd.html');
    }else{
    /* 在庫情報更新処理 */
        /* POSTデータでテーブルを更新 */
        $sql = 'UPDATE goods SET GoodsName="'.$post['GoodsName'].'",'
                                   .'Supplier="'.$post['Supplier'].'",'
                                   .'PurchasePrice="'.$post['PurchasePrice'].'",'
                                   .'Price="'.$post['Price'].'",'
                                   .'Inventory="'.$post['Inventory'].'",'
                                   .'Place="'.$post['Place'].'"'
                                   .' WHERE code = '.$post['code'] ;
        $result=$dbh->query($sql);
        /* 添付ファイルを処理する */
        $temp_file_name_org = '';
        if(is_uploaded_file($_FILES['upload_file']['tmp_name'])){
            $finfo = new finfo(FILEINFO_MIME_TYPE);
            $mime_type = $finfo->file($_FILES['upload_file']['tmp_name']);
            $res = finfo_close($finfo);
            /* getimagesize関数で画像情報を取得する */
            list($img_width, $img_height, $mime_type, $attr) = getimagesize($_FILES['upload_file']['tmp_name']);
            switch($mime_type){
                /* jpegの場合 */
                case IMAGETYPE_JPEG:
                    $img_extension = "jpg";
                    break;
                /* pngの場合 */
                case IMAGETYPE_PNG:
                    $img_extension = "png";
                    break;
                /* gifの場合 */
                case IMAGETYPE_GIF:
                    $img_extension = "gif";
                    break;
            }
            /* 拡張子が画像だったか? */
            if(isset($img_extension)){
                /* ファイルのアップロード */
                $temp_file_name_org = $post['GoodsName'].'_'.date('YmdHis').'.'.$img_extension ;
                $temp_file_name     = './image/'.$temp_file_name_org ;
                move_uploaded_file($_FILES['upload_file']['tmp_name'], $temp_file_name);
            }
        }
        /* 添付ファイル名が空ではない? */
        if(!empty($temp_file_name_org)){
            $sql = 'SELECT * FROM goods WHERE code='.$post['code'];
            $godds_stmt=$dbh->prepare($sql);
            $godds_stmt->execute();
            $goods_rec = $godds_stmt->fetch(PDO::FETCH_ASSOC);
            /* 更新前の添付ファイルを削除 */
            if($goods_rec){
                $file = './image/'.$goods_rec['Image'];
                unlink($file);
            }
            /* 添付ファイル更新 */
            $sql = 'UPDATE goods SET Image="'.$temp_file_name_org.'" WHERE code = '.$post['code'] ;
            $result=$dbh->query($sql);
        }
        /* 在庫一覧画面を表示する */
        header('Location:ItemList.html');
    }
    exit();
}catch(Exception $e){
    /* ログイン画面を表示する */
    header('Location:index.html');
    exit();
}
?>

以前に作成した新規在庫情報登録処理を、修正に対応させます。

if(isset($post[‘code’])==false)の条件式で、TRUEの場合は以前作成した新規在庫情報登録処理を実行します。(新規在庫情報登録の時は、codeはPOSTしない。)
if(isset($post[‘code’])==false)ではない(つまり、if(isset($post[‘code’])==true))の時は、POSTデータで、codeに対するレコードをUPDATEします。

もし画像が更新されているときは、以前に登録していた画像を削除(unlink)してから、新しい画像に差し替えます。

在庫情報編集後

在庫情報削除

在庫情報編集画面で削除ボタンを選択した場合は、ItemDelete.php画像データとテーブル内のcodeに対するレコードを削除(DELETE)し、在庫一覧画面(ItemList.html)を表示します。

<?php
session_start();
if( !isset( $_SESSION['login_flg'] ) ) {
    print 'ログインしてください。<a href="index.html">ログイン</a>';
    exit();
}
try{
   if(isset($_GET['code'])==true){
    /* 外部ファイル読み込み */
        require_once('common/common.php');
        /* データベース関係の処理 */
        get_database_data($dsn,$user,$password);
        $dbh = new PDO($dsn,$user,$password);
        $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    /* レコード削除処理 */
        /* 添付ファイルを削除 */
        $sql = 'SELECT * FROM goods WHERE code='.$_GET['code'];
        $godds_stmt=$dbh->prepare($sql);
        $godds_stmt->execute();
        $goods_rec = $godds_stmt->fetch(PDO::FETCH_ASSOC);
        if($goods_rec){
            $file = './image/'.$goods_rec['Image'];
            unlink($file);
        }
        /* POSTデータをデータベースに登録処理 */
        $sql = 'DELETE FROM goods WHERE code='.$_GET['code'];
        $result=$dbh->query($sql);
    }
    /* 在庫一覧画面を表示する */
    header('Location:ItemList.html');
    exit();
}catch(Exception $e){
    /* ログイン画面を表示する */
    header('Location:index.html');
    exit();
}
?>

ここまでのファイル・フォルダ構成の確認

ここまでで作成したファイルは下記画像を参照ください。

在庫情報編集画面を作ろう(ファイル・フォルダ構成)