반응형

 

 

상품을 등록할때 옵션이 있는 경우는 

 

1.옵션이 없을때

2. 옵션이 한개일때

3. 옵션이 여러개일때

4. 옵션마다 재고와 가격이 다를때

 

등등이 있겠다. 옵션이 없을때는 했고 이번에는 옵션이 한개일때를 해보자. 옵션이 한개이던 여러개이건 가격이 같고 재고가 같으면 크게 문제가 안되는데 옵션마다 가격이 다르고 재고가 다르면 골치아프다.

 

우선 옵션이하나일때부터 알아보자. 방법은 다양하겠지만 이런 방법도 있구나라고 생각하면 된다.

 

상품등록 페이지를 수정해보자. 옵션 부분을 추가한다.

 

/admin/product/product_up.php

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/header.php";
if(!$_SESSION['AUID']){
    echo "<script>alert('권한이 없습니다.');history.back();</script>";
    exit;
}


$query="select * from category where step=1";
$result = $mysqli->query($query) or die("query error => ".$mysqli->error);
while($rs = $result->fetch_object()){
    $cate1[]=$rs;
}

?>
<style>
    .thst{
        text-align: center;
    vertical-align: middle;
    }
</style>

        <div style="text-align:center;padding:20px;"><H3>제품등록하기</H3></div>
<form method="post" action="pupok.php" onsubmit="return save()" enctype="multipart/form-data">        
        <table class="table table-sm table-bordered">
          <tbody>
            <input type="hidden" name="file_table_id" id="file_table_id" value="">
            <input type="hidden" name="contents" id="contents" value="">
           
          <tr>
            <th scope="row" class="thst">카테고리선택</th>
            <td>
            <div class="row g-3">
                <div class="col-md-4">
                    <select class="form-select" name="cate1" id="cate1" aria-label="Default select example">
                        <option value="">대분류</option>
                        <?php
                            foreach($cate1 as $c){
                        ?>
                            <option value="<?php echo $c->code;?>"><?php echo $c->name;?></option>
                        <?php }?>
                    </select>
                </div>
                <div class="col-md-4">
                    <select class="form-select" name="cate2" id="cate2" aria-label="Default select example">
                        <option value="">중분류</option>
                    </select>
                </div>
                <div class="col-md-4">
                    <select class="form-select" name="cate3" id="cate3" aria-label="Default select example">
                        <option value="">소분류</option>
                    </select>
                </div>
            </div>
            </td>
           
          </tr>
          <tr>
            <th scope="row" class="thst">제품명</th>
            <td><input type="text" class="form-control" name="name" id="name"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">택배비</th>
            <td><input type="number" style="width:200px;text-align:right;" class="form-control" name="delivery_fee" id="delivery_fee"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">제품가격</th>
            <td><input type="number" style="width:200px;text-align:right;" class="form-control" name="price" id="price"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">세일가격</th>
            <td><input type="number" style="width:200px;text-align:right;" class="form-control" name="sale_price" id="sale_price"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">세일비율</th>
            <td><input type="number" style="width:200px;text-align:right;" class="form-control" name="sale_ratio" id="sale_ratio"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">재고</th>
            <td><input type="number" style="width:200px;text-align:right;" class="form-control" name="cnt" id="cns"></td>
          </tr>
          <tr>
            <th scope="row" class="thst">전시옵션</th>
            <td>
            <input class="form-check-input" type="checkbox" name="ismain" id="ismain" value="1">메인&nbsp;
            <input class="form-check-input" type="checkbox" name="isnew" id="isnew" value="1">신제품&nbsp;
            <input class="form-check-input" type="checkbox" name="isbest" id="isbest" value="1">베스트&nbsp;
            <input class="form-check-input" type="checkbox" name="isrecom" id="isrecom" value="1">추천&nbsp;
            </td>
          </tr>
          <tr>
            <th scope="row" class="thst">위치지정</th>
            <td>
                <select class="form-select" name="locate" id="locate" aria-label="Default select example">
                    <option value="0">지정안함</option>
                    <option value="1">1번위치</option>
                    <option value="2">2번위치</option>
                </select>
            </td>
          </tr>
          <tr>
            <th scope="row" class="thst">판매종료일</th>
            <td>
                <input type="text" class="form-control" style="width: 272px;" name="sale_end_date" id="sale_end_date" value="<?php echo date("Y-m-d",strtotime("+6 month"))?>">
            </td>
          </tr>
          <tr>
            <th scope="row" class="thst">제품상세설명</th>
            <td>
                <div id="summernote"></div>
            </td>
          </tr>
          <tr>
            <th scope="row" class="thst">썸네일</th>
            <td><input type="file" class="form-control" name="thumbnail" id="thumbnail"></td>
          </tr>
          <tr style="max-height:100px;">
            <th scope="row" class="thst">추가이미지</th>
            <td style="height:100px;">
                <input type="file" multiple name="upfile[]" id="upfile" style="display:none;">
                <div id="target_file_wrap">
                    <a href="#" onclick="jQuery('#upfile').click()" class="btn btn-primary">이미지선택</a>
                </div>                    
                <div class="row row-cols-1 row-cols-md-6 g-4" id="imageArea">
                </div>
            </td>
          </tr>
          <tr>
            <th scope="row" class="thst">
                <select class="form-select" name="optionCate1" id="optionCate1">
                    <option value="컬러" selected>컬러</option>
                </select>
            </th>
            <td>
                <table class="table">
                <thead>
                    <tr>
                    <th scope="col">옵션명</th>
                    <th scope="col">재고</th>
                    <th scope="col">가격</th>
                    <th scope="col">이미지</th>
                    </tr>
                </thead>
                <tbody id="option1">
                    <tr id="optionTr1">
                    <th scope="row">
                        <input class="form-control" type="text" style="max-width:200px;" value="" name="optionName1[]">
                    </th>
                    <td>
                        <div class="input-group">
                            <input type="text" class="form-control" style="max-width:100px;" value="0" name="optionCnt1[]">
                            <span class="input-group-text"></span>
                        </div>
                    </td>
                    <td>
                        <div class="input-group">
                            <input type="text" class="form-control" style="max-width:100px;" value="0" name="optionPrice1[]">
                            <span class="input-group-text"></span>
                        </div>
                    </td>
                    <td>
                        <input type="file" class="form-control" name="optionImage1[]" id="optionImage1">
                    </td>
                    </tr>
                </tbody>
                </table>
                <button class="btn btn-secondary" type="button" onclick="opt1cp()">옵션추가</button>
            </td>
          </tr>
         
          </tbody>
        </table>
       
        <button class="btn btn-primary" type="submit">등록완료</button>
</form>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script>

    function opt1cp(){
        var addHtml=$("#optionTr1").html();
        var addHtml="<tr>"+addHtml+"</tr>";
        $("#option1").append(addHtml);
    }

    function save(){
        var markup = $('#summernote').summernote('code');
          var contents=encodeURIComponent(markup);
          $("#contents").val(contents);
    }

    $(function(){
        $('#summernote').summernote({
            height: 300
        });
        $("#sale_end_date").datepicker({ dateFormat: 'yy-mm-dd' });
    });

    $("#cate1").change(function(){
        var cate1 = $("#cate1 option:selected").val();
       
        var data = {
            cate1 : cate1
        };
            $.ajax({
                async : false ,
                type : 'post' ,
                url : 'category2.php' ,
                data  : data ,
                dataType : 'html' ,
                error : function() {} ,
                success : function(return_data) {
                    $("#cate2").html(return_data);
                }
        });
    });

    $("#cate2").change(function(){
        var cate2 = $("#cate2 option:selected").val();
       
        var data = {
            cate2 : cate2
        };
            $.ajax({
                async : false ,
                type : 'post' ,
                url : 'category3.php' ,
                data  : data ,
                dataType : 'html' ,
                error : function() {} ,
                success : function(return_data) {
                    $("#cate3").html(return_data);
                }
        });
    });  

    $("#upfile").change(function(){

        var files = $('#upfile').prop('files');
        for(var i=0; i < files.length; i++) {
            attachFile(files[i]);
        }

        $('#upfile').val('');

    });  

    function attachFile(file) {
    var formData = new FormData();
    formData.append("savefile", file);
    $.ajax({
        url: 'product_save_image.php',
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        dataType : 'json' ,
        type: 'POST',
        success: function (return_data) {
            if(return_data.result=="member"){
                alert('로그인 하십시오.');
                return;
            }else if(return_data.result=="size"){
                alert('10메가 이하만 첨부할 수 있습니다.');
                return;
            }else if(return_data.result=="image"){
                alert('이미지 파일만 첨부할 수 있습니다.');
                return;
            }else if(return_data.result=="error"){
                alert('첨부하지 못했습니다. 관리자에게 문의하십시오.');
                return;
            }else{
                imgid = $("#file_table_id").val() + return_data.imgid + ",";
                $("#file_table_id").val(imgid);
                var html = "<div class='col' id='f_"+return_data.imgid+"'><div class='card h-100'><img src='/pdata/"+return_data.savename+"' class='card-img-top'><div class='card-body'><button type='button' class='btn btn-warning' onclick='file_del("+return_data.imgid+")'>삭제</button></div></div></div>";
                $("#imageArea").append(html);
            }
        }
    });

    }

    function file_del(imgid){

        if(!confirm('삭제하시겠습니까?')){
        return false;
        }
           
        var data = {
            imgid : imgid
        };
            $.ajax({
                async : false ,
                type : 'post' ,
                url : 'image_delete.php' ,
                data  : data ,
                dataType : 'json' ,
                error : function() {} ,
                success : function(return_data) {
                    if(return_data.result=="member"){
                        alert('로그인 하십시오.');
                        return;
                    }else if(return_data.result=="my"){
                        alert('본인이 작성한 제품의 이미지만 삭제할 수 있습니다.');
                        return;
                    }else if(return_data.result=="no"){
                        alert('삭제하지 못했습니다. 관리자에게 문의하십시오.');
                        return;
                    }else{
                        $("#f_"+imgid).hide();
                    }
                }
        });

        }

</script>    
<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/footer.php";
?>
옵션분류는 둘중 하나다. 컬러 아니면 사이즈. 이중 컬러에만 옵션이미지를 넣으려고 한다. 옵션은 여러개 들어갈 수 있으니 추가를 위해서 옵션추가 버튼을 이용해서 옵션부분의 html을 추가하도록 했다.
각 항목을 배열로 저장해서 넘기면 된다. 당연히 받는 곳에서 배열로 받아서 값이 있으면 컬러라는 옵션을 넣어주면된다. 옵션이 하나인 경우에는 간단한 편이다. 어차피 가격도 같고 재고는 옵션에 재고가 있으면 옵션 재고를 보여준다.
이제 이 값을 저장하기 위해 테이블을 하나 만들어보자.


CREATE TABLE `product_options` (
  `poid` int(11) NOT NULL AUTO_INCREMENT,
  `pid` int(11) DEFAULT NULL,
  `cate` varchar(100) DEFAULT NULL,
  `option_name` varchar(100) DEFAULT NULL,
  `option_cnt` int(11) DEFAULT NULL,
  `option_price` int(11) DEFAULT NULL,
  `image_url` varchar(300) DEFAULT NULL,
  `status` tinyint(4) DEFAULT 1,
  PRIMARY KEY (`poid`),
  KEY `newtable_pid_IDX` (`pid`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;

늘 얘기하지만 이런 테이블 설계는 나중에는 직접 해볼 기회가 있을 것이다. 히지만 대부분은 기본에 있던 테이블을 사용하는 경우가 더 많을 것이다. 그러니 그냥 따라하자. 

자 이제 만들어진 테이블에 옵션을 저장해보자.

 

/admin/product/pupok.php

<?php session_start();
include $_SERVER["DOCUMENT_ROOT"]."/inc/dbcon.php";
ini_set( 'display_errors', '0' );

if(!$_SESSION['AUID']){
    echo "<script>alert('권한이 없습니다.');history.back();</script>";
    exit;
}


$cate=$_POST["cate1"].$_POST["cate2"].$_POST["cate3"];//대중소분류를 모두 저장한다.
$name=$_POST["name"];//제품명
$delivery_fee=$_POST["delivery_fee"];//택배비
$price=$_POST["price"];//가격
$sale_price=$_POST["sale_price"];//세일가
$sale_ratio=$_POST["sale_ratio"];//세일비율
$cnt=$_POST["cnt"];//재고
$contents=rawurldecode($_POST['contents']);//제품 설명
$ismain=$_POST["ismain"];//메인
$isnew=$_POST["isnew"];//신상품
$isbest=$_POST["isbest"];//베스트
$isrecom=$_POST["isrecom"];//추천
$locate=$_POST["locate"];//위치
$sale_end_date=$_POST["sale_end_date"];//판매종료일
$file_table_id=$_POST["file_table_id"];//이미지
$file_table_id=rtrim($file_table_id,",");//오른쪽 끝에 , 삭제
$optionCate1=$_POST["optionCate1"];//옵션분류

if($_FILES["thumbnail"]["name"]){//첨부한 파일이 있으면

        if($_FILES['thumbnail']['size']>10240000){//10메가
            echo "<script>alert('10메가 이하만 첨부할 수 있습니다.');history.back();</script>";
            exit;
        }

        if($_FILES['thumbnail']['type']!='image/jpeg' and $_FILES['thumbnail']['type']!='image/gif' and $_FILES['thumbnail']['type']!='image/png'){//이미지가 아니면, 다른 type은 and로 추가
            echo "<script>alert('이미지만 첨부할 수 있습니다.');history.back();</script>";
            exit;
        }

        $save_dir = $_SERVER['DOCUMENT_ROOT']."/pdata/";//파일을 업로드할 디렉토리
        $filename = $_FILES["thumbnail"]["name"];
        $ext = pathinfo($filename,PATHINFO_EXTENSION);//확장자 구하기
        $newfilename = date("YmdHis").substr(rand(),0,6);
        $thumbnail = $newfilename.".".$ext;//새로운 파일이름과 확장자를 합친다
       
        if(move_uploaded_file($_FILES["thumbnail"]["tmp_name"], $save_dir.$thumbnail)){
            $thumbnail = "/pdata/".$thumbnail;
        }else{
            echo "<script>alert('이미지를 등록할 수 없습니다. 관리자에게 문의해주십시오.');history.back();</script>";
            exit;
        }

}

$sale_cnt = 0;//판매량
$query="INSERT INTO products
(name, cate, content, thumbnail, price, sale_price, sale_ratio, cnt, sale_cnt, isnew, isbest, isrecom, ismain, locate, userid, sale_end_date, reg_date, delivery_fee)
VALUES('$name'
, '".$cate."'
, '".$contents."'
, '".$thumbnail."'
, '".$price."'
, '".$sale_price."'
, '".$sale_ratio."'
, ".$cnt."
, ".$sale_cnt."
, '".$isnew."'
, '".$isbest."'
, '".$isrecom."'
, '".$ismain."'
, '".$locate."'
, '".$_SESSION['AUID']."'
, '".$sale_end_date."'
, now()
, '".$delivery_fee."'
)";

$rs=$mysqli->query($query) or die($mysqli->error);
$pid = $mysqli -> insert_id;
if($rs){

    //옵션부분
    $optionName1=$_REQUEST["optionName1"];//옵션명
    $optionCnt1=$_REQUEST["optionCnt1"];//재고
    $optionPrice1=$_REQUEST["optionPrice1"];//가격

    if($_FILES["optionImage1"]["name"][0]){//첨부한 파일이 있으면

        for($k=0;$k<count($_FILES["optionImage1"]["name"]);$k++){

            if($_FILES['optionImage1']['size'][$k]>10240000){//10메가
                echo "<script>alert('10메가 이하만 첨부할 수 있습니다.');history.back();</script>";
                exit;
            }

            if($_FILES['optionImage1']['type'][$k]!='image/jpeg' and $_FILES['optionImage1']['type'][$k]!='image/gif' and $_FILES['optionImage1']['type'][$k]!='image/png'){//이미지가 아니면, 다른 type은 and로 추가
                echo "<script>alert('이미지만 첨부할 수 있습니다.');history.back();</script>";
                exit;
            }

            $save_dir = $_SERVER['DOCUMENT_ROOT']."/pdata/optiondata/";//파일을 업로드할 디렉토리
            $filename = $_FILES["optionImage1"]["name"][$k];
            $ext = pathinfo($filename,PATHINFO_EXTENSION);//확장자 구하기
            $newfilename = date("YmdHis").substr(rand(),0,6);
            $optionImage1 = $newfilename.".".$ext;//새로운 파일이름과 확장자를 합친다
           
            if(move_uploaded_file($_FILES["optionImage1"]["tmp_name"][$k], $save_dir.$optionImage1)){
                $upload_option_image[]="/pdata/optiondata/".$optionImage1;
            }

        }

    }

    $k=0;
    foreach($optionName1 as $on){

        if($on){
            $optQuery="INSERT INTO testdb.product_options
            (pid, cate, option_name, option_cnt, option_price, image_url)
            VALUES (".$pid.", '".$optionCate1."', '".$on."', ".$optionCnt1[$k].", ".$optionPrice1[$k].", '".$upload_option_image[$k]."')";
            $ofs=$mysqli->query($optQuery) or die($mysqli->error);
            $k++;
        }
    }

    if($file_table_id){//첨부한 이미지 테이블 업데이트
        $upquery="update product_image_table set pid=".$pid." where imgid in (".$file_table_id.")";
        $fs=$mysqli->query($upquery) or die($mysqli->error);
    }

    echo "<script>alert('등록했습니다.');location.href='/admin/product/product_list.php';</script>";
    exit;

}else{
    echo "<script>alert('등록하지 못했습니다. 관리자에게 문의해주십시오.');history.back();</script>";
    exit;
}


?>

보면 알겠지만 새로운 소스는 없다. 기존에 했던거를 응용한거다. 옵션부분에서 새로 생긴 값들을 배열로 받아서 각각 저장했다. 1이 붙어있는 변수는 옵션분류가 "컬러"다. 2로 받으면 "사이즈'다. 물론 이것도 앞에서 옵션분류를 만들어서 하면 되는데 취찮아서...

 

다음엔 이렇게 만든 제품을 구매할 수 있도록 구매 페이지를 만들어보자.

 

 

반응형

+ Recent posts