반응형

 

 

* 댓글에 파일을 첨부할때 파일의 정보를 저장하는 테이블인 file_table의 이름을 file_table_memo로 수정했다. 

 

이 소스에는 오류가 있다. 댓글에 무조건 첨부파일이 있다고 가정하고 만들어 졌다. 첨부파일이 없는 경우도 있으므로 아래 링크로 가서 수정된 소스를 확인하자.

 

https://programmerdaddy.tistory.com/269

 

이번엔 댓글을 쓸때 이미지를 첨부하는 기능을 만들어보자. 일단 view.php를 수정한다.

 

/view.php

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/header.php";

$bid=$_GET["bid"];
$result = $mysqli->query("select * from board where bid=".$bid) or die("query error => ".$mysqli->error);
$rs = $result->fetch_object();

$query="select * from memo m
join file_table_memo f on m.memoid=f.memoid
where m.status=1 and m.bid=".$rs->bid." order by m.memoid asc";
$memo_result = $mysqli->query($query) or die("query error => ".$mysqli->error);
while($mrs = $memo_result->fetch_object()){
    $memoArray[]=$mrs;
}

$fquery="select * from file_table where status=1 and bid=".$rs->bid." and memoid is null order by fid asc";
$file_result = $mysqli->query($fquery) or die("query error => ".$mysqli->error);
while($frs = $file_result->fetch_object()){
    $fileArray[]=$frs;
}

$query2="select type,count(*) as cnt from recommend r where bid=".$rs->bid." group by type";
$rec_result = $mysqli->query($query2) or die("query error => ".$mysqli->error);
while($recs = $rec_result->fetch_object()){
  $recommend[$recs->type] = $recs->cnt;
}

?>

<style>
  img {
    max-width:90%;
  }
</style>

      <h3 class="pb-4 mb-4 fst-italic border-bottom" style="text-align:center;">
        - 게시판 보기 -
      </h3>

      <article class="blog-post">
        <h2 class="blog-post-title"><?php echo $rs->subject;?></h2>
        <p class="blog-post-meta"><?php echo $rs->regdate;?> by <a href="#"><?php echo $rs->userid;?></a></p>

        <hr>
        <?php
          foreach($fileArray as $fa){
        ?>
          <p><img src="/data/<?php echo $fa->filename;?>"></p>
        <?php }?>
        <p>
          <?php echo $rs->content;?>
        </p>
       
        <div style="text-align:center;">
          <button type="button" class="btn btn-lg btn-primary" id="like_button">추천&nbsp;<span id="like"><?php echo number_format($recommend['like']);?></span></button>
          <button type="button" class="btn btn-lg btn-warning" id="hate_button">반대&nbsp;<span id="hate"><?php echo number_format($recommend['hate']);?></span></button>
        </div>
        <hr>
      </article>

     

      <nav class="blog-pagination" aria-label="Pagination">
        <a class="btn btn-outline-secondary" href="/index.php">목록</a>
        <a class="btn btn-outline-secondary" href="/write.php?parent_id=<?php echo $rs->bid;?>">답글</a>
        <a class="btn btn-outline-secondary" href="/write.php?bid=<?php echo $rs->bid;?>">수정</a>
        <a class="btn btn-outline-secondary" href="/delete.php?bid=<?php echo $rs->bid;?>" onclick="return confirm('삭제하시겠습니까?');">삭제</a>
      </nav>

      <div style="margin-top:20px;">
        <form class="row g-3">
          <input type="hidden" name="file_table_id" id="file_table_id" value="">
          <div class="col-md-8">
            <textarea class="form-control" placeholder="댓글을 입력해주세요." id="memo" style="height: 60px"></textarea>
          </div>
          <div class="col-md-2">
            <button type="button" class="btn btn-secondary" id="memo_button">댓글등록</button>
          </div>
          <div class="col-md-2" id="memo_image">
            <input type="file" name="upfile" id="upfile" />
          </div>
        </form>
      </div>
      <div id="memo_place">
      <?php
        foreach($memoArray as $ma){
      ?>
        <div class="card mb-4" id="memo_<?php echo $ma->memoid?>" style="max-width: 100%;margin-top:20px;">
          <div class="row g-0">
            <div class="col-md-12">
              <div class="card-body">
                <p class="card-text">
                <img src="/data/<?php echo $ma->filename;?>" style="max-width:90%;">
                <br>  
                <?php echo $ma->memo;?></p>
                <p class="card-text"><small class="text-muted"><?php echo $ma->userid;?> / <?php echo $ma->regdate;?></small></p>
                <p class="card-text" style="text-align:right"><a href="javascript:;" onclick="memo_modi(<?php echo $ma->memoid?>)">수정</a> / <a href="javascript:;" onclick="memo_del(<?php echo $ma->memoid?>)">삭제</a></p>
              </div>
            </div>
          </div>
        </div>
      <?php }?>
      </div>

<script>

  $("#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: 'save_image_memo.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{
                $("#file_table_id").val(return_data.fid);
                var html = "<div class='col' id='f_"+return_data.fid+"'><div class='card h-100'><img src='/data/"+return_data.savename+"' class='card-img-top'><div class='card-body'><button type='button' class='btn btn-warning' onclick='file_del("+return_data.fid+")'>삭제</button></div></div></div>";
                $("#upfile").hide();
                $("#memo_image").append(html);
            }
        }
    });

  }

  function file_del(fid){

    if(!confirm('삭제하시겠습니까?')){
    return false;
    }

    var data = {
        fid : fid
    };
        $.ajax({
            async : false ,
            type : 'post' ,
            url : 'file_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{
                    $("#file_table_id").val('');
                    $("#f_"+fid).hide();
                    $("#upfile").show();
                }
            }
    });

    }

  $("#like_button").click(function () {

    if(!confirm('추천하시겠습니까?')){
      return false;
    }
     
      var data = {
          type : 'like' ,
          bid : <?php echo $bid;?>
      };
          $.ajax({
              async : false ,
              type : 'post' ,
              url : 'like_hate.php' ,
              data  : data ,
              dataType : 'json' ,
              error : function() {} ,
              success : function(return_data) {
                if(return_data.result=="member"){
                  alert('로그인 하십시오.');
                  return;
                }else if(return_data.result=="check"){
                  alert('이미 추천이나 반대를 하셨습니다.');
                  return;
                }else if(return_data.result=="no"){
                  alert('다시한번 시도해주십시오.');
                  return;
                }else{
                  $("#like").text(return_data.cnt);
                }
              }
          });
  });

  $("#hate_button").click(function () {

    if(!confirm('반대하시겠습니까?')){
      return false;
    }
     
      var data = {
          type : 'hate' ,
          bid : <?php echo $bid;?>
      };
          $.ajax({
              async : false ,
              type : 'post' ,
              url : 'like_hate.php' ,
              data  : data ,
              dataType : 'json' ,
              error : function() {} ,
              success : function(return_data) {
                if(return_data.result=="member"){
                  alert('로그인 하십시오.');
                  return;
                }else if(return_data.result=="check"){
                  alert('이미 추천이나 반대를 하셨습니다.');
                  return;
                }else if(return_data.result=="no"){
                  alert('다시한번 시도해주십시오.');
                  return;
                }else{
                  $("#hate").text(return_data.cnt);
                }
              }
          });
  });


  $("#memo_button").click(function () {
        var file_table_id = $("#file_table_id").val();
        var data = {
            memo : $('#memo').val() ,
            bid : <?php echo $bid;?>,
            file_table_id : $('#file_table_id').val()
        };
            $.ajax({
                async : false ,
                type : 'post' ,
                url : 'memo_write.php' ,
                data  : data ,
                dataType : 'html' ,
                error : function() {} ,
                success : function(return_data) {
                  if(return_data=="member"){
                    alert('로그인 하십시오.');
                    return;
                  }else{
                    $('#memo').val('')
                    $("#file_table_id").val('');
                    $("#f_"+file_table_id).hide();
                    $("#upfile").show();
                    $("#memo_place").append(return_data);
                  }
                }
        });
    });

  function memo_del(memoid){

    if(!confirm('삭제하시겠습니까?')){
      return false;
    }
   
    var data = {
        memoid : memoid
    };
        $.ajax({
            async : false ,
            type : 'post' ,
            url : 'memo_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{
                $("#memo_"+memoid).hide();
              }
            }
    });

  }

  function memo_modi(memoid){

    var data = {
        memoid : memoid
    };
   
    $.ajax({
          async : false ,
          type : 'post' ,
          url : 'memo_modify.php' ,
          data  : data ,
          dataType : 'html' ,
          error : function() {} ,
          success : function(return_data) {
            if(return_data=="member"){
              alert('로그인 하십시오.');
              return;
            }else if(return_data=="my"){
              alert('본인이 작성한 글만 수정할 수 있습니다.');
              return;
            }else if(return_data=="no"){
              alert('수정하지 못했습니다. 관리자에게 문의하십시오.');
              return;
            }else{
              $("#memo_"+memoid).html(return_data);
            }
          }
    });

  }

  function memo_modify(memoid){

    var data = {
        memoid : memoid,
        memo : $('#memo_text_'+memoid).val()
    };

    $.ajax({
          async : false ,
          type : 'post' ,
          url : 'memo_modify_update.php' ,
          data  : data ,
          dataType : 'html' ,
          error : function() {} ,
          success : function(return_data) {
            if(return_data=="member"){
              alert('로그인 하십시오.');
              return;
            }else if(return_data=="my"){
              alert('본인이 작성한 글만 수정할 수 있습니다.');
              return;
            }else if(return_data=="no"){
              alert('수정하지 못했습니다. 관리자에게 문의하십시오.');
              return;
            }else{
              $("#memo_"+memoid).html(return_data);
            }
          }
    });

    }

</script>

<?php
include $_SERVER["DOCUMENT_ROOT"]."/inc/footer.php";
?>

댓글을 쓰는 부분에 이미지를 첨부할 수 있도록 버튼을 달았다. 이미지를 첨부하면 화면에 보여준다. 이때 ajax를 이용한다. ajax처리를 위한 save_image_memo.php를 만들어보자.

 

그리고 메모에 첨부한 파일의 정보를 저장할 테이블을 하나 만든다.

CREATE TABLE `file_table_memo` (
  `fid` int(11) NOT NULL AUTO_INCREMENT,
  `bid` int(11) DEFAULT NULL,
  `userid` varchar(100) DEFAULT NULL,
  `filename` varchar(100) DEFAULT NULL,
  `regdate` datetime DEFAULT current_timestamp(),
  `status` tinyint(4) DEFAULT 1,
  `memoid` int(11) DEFAULT NULL,
  `type` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`fid`),
  KEY `idx_file_table_userid` (`userid`),
  KEY `idx_file_table_type` (`type`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

/save_image_memo.php

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

if(!$_SESSION['UID']){
    $retun_data = array("result"=>"member");
    echo json_encode($retun_data);
    exit;
}

if($_FILES['savefile']['size']>10240000){//10메가
    $retun_data = array("result"=>"size");
    echo json_encode($retun_data);
    exit;
}

if($_FILES['savefile']['type']!='image/jpeg' and $_FILES['savefile']['type']!='image/gif' and $_FILES['savefile']['type']!='image/png'){//이미지가 아니면, 다른 type은 and로 추가
    $retun_data = array("result"=>"image");
    echo json_encode($retun_data);
    exit;
}

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

if(move_uploaded_file($_FILES["savefile"]["tmp_name"], $save_dir.$savefile)){//파일 등록에 성공하면 디비에 등록해준다.
    $sql="INSERT INTO testdb.file_table_memo
    (userid, filename)
    VALUES('".$_SESSION['UID']."', '".$savefile."')";
    $result = $mysqli->query($sql) or die($mysqli->error);
    $fid = $mysqli -> insert_id;
    $retun_data = array("result"=>"success", "fid"=>$fid, "savename"=>$savefile);
    echo json_encode($retun_data);
    exit;
}else{
    $retun_data = array("result"=>"error");
    echo json_encode($retun_data);
    exit;
}


?>
       

이전에 했던 파일이랑 비슷하다. 그다음엔 첨부된 이미지 파일을 댓글 등록시 memoid값을 입력하도록 memo_write.php를 수정한다.

/memo_write.php

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

if(!$_SESSION['UID']){
    echo "member";
    exit;
}

$memo  = $_POST['memo'];
$bid  = $_POST['bid'];
$memoid = $_POST['memoid']??0;
$file_table_id = $_POST['file_table_id'];

$sql="INSERT INTO memo
(bid, pid, userid, memo, status)
VALUES(".$bid.", ".$memoid.", '".$_SESSION['UID']."', '".$memo."', 1)";
$result=$mysqli->query($sql) or die($mysqli->error);
if($result)$last_memoid = $mysqli -> insert_id;

//메모 첨부 이미지 업데이트
$uq="update file_table_memo set bid=".$bid.", memoid=".$last_memoid." where fid=".$file_table_id;
$ur=$mysqli->query($uq) or die($mysqli->error);

$fquery="select * from file_table_memo where status=1 and fid=".$file_table_id;
$file_result = $mysqli->query($fquery) or die("query error => ".$mysqli->error);
$frs = $file_result->fetch_object();
$img = "<img src='/data/".$frs->filename."' style='max-width:90%'>";

echo "<div class=\"card mb-4\" id=\"memo_".$last_memoid."\" style=\"max-width: 100%;margin-top:20px;\">
<div class=\"row g-0\">
    <div class=\"col-md-12\">
    <div class=\"card-body\">
      <p class=\"card-text\">".$img."<br>".$memo."</p>
      <p class=\"card-text\"><small class=\"text-muted\">".$_SESSION['UID']." / now</small></p>
      <p class=\"card-text\" style=\"text-align:right\"><a href=\"javascript:;\" onclick=\"memo_modi(".$last_memoid.")\">수정</a> / <a href=\"javascript:;\" onclick=\"memo_del(".$last_memoid.")\">삭제</a></p>
    </div>
  </div>
</div>
</div>";

?>
   

디비를 업데이트해주고 화면에 메모와 이미지를 같이 뿌려준다. 이번엔 수정처리를 위한 memo_update_modify.php를 수정한다.

/memo_modify_update.php

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

if(!$_SESSION['UID']){
    echo "member";
    exit;
}

$memoid = $_POST['memoid'];
$memo = $_POST['memo'];

$result = $mysqli->query("select * from memo where memoid=".$memoid) or die("query error => ".$mysqli->error);
$rs = $result->fetch_object();

if($rs->userid!=$_SESSION['UID']){
    echo "my";
    exit;
}

$sql="update memo set memo='".$memo."' where memoid=".$memoid;//status값을 바꿔준다.
$result=$mysqli->query($sql) or die($mysqli->error);

$fquery="select * from file_table_memo where status=1 and memoid=".$memoid;
$file_result = $mysqli->query($fquery) or die("query error => ".$mysqli->error);
$frs = $file_result->fetch_object();
$img = "<img src='/data/".$frs->filename."' style='max-width:90%'>";


echo "<div class=\"row g-0\">
    <div class=\"col-md-12\">
    <div class=\"card-body\">
      <p class=\"card-text\">".$img."<br>".$memo."</p>
      <p class=\"card-text\"><small class=\"text-muted\">".$_SESSION['UID']." / now</small></p>
      <p class=\"card-text\" style=\"text-align:right\"><a href=\"javascript:;\" onclick=\"memo_modi(".$memoid.")\">수정</a> / <a href=\"javascript:;\" onclick=\"memo_del(".$memoid.")\">삭제</a></p>
    </div>
  </div>
</div>";

?>
   

그리고 댓글을 삭제할때 첨부된 이미지가 있으면 함께 삭제하도록 memo_delete.php를 수정한다.

/memo_delete.php

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

if(!$_SESSION['UID']){
    $retun_data = array("result"=>"member");
    echo json_encode($retun_data);
    exit;
}

$memoid = $_POST['memoid'];

$result = $mysqli->query("select * from memo where memoid=".$memoid) or die("query error => ".$mysqli->error);
$rs = $result->fetch_object();

if($rs->userid!=$_SESSION['UID']){
    $retun_data = array("result"=>"my");
    echo json_encode($retun_data);
    exit;
}

$sql="update memo set status=0 where memoid=".$memoid;//status값을 바꿔준다.
$result=$mysqli->query($sql) or die($mysqli->error);
if($result){
   
    $fquery="select * from file_table_memo where status=1 and memoid=".$memoid;
    $file_result = $mysqli->query($fquery) or die("query error => ".$mysqli->error);
    $frs = $file_result->fetch_object();
    $delete_file=$_SERVER["DOCUMENT_ROOT"]."/data/".$frs->filename;
    if(unlink($delete_file)){
        $sql2="update file_table_memo set status=0 where fid=".$frs->fid;//status값을 바꿔준다.
        $result2=$mysqli->query($sql2) or die($mysqli->error);
    }

    $retun_data = array("result"=>"ok");
    echo json_encode($retun_data);
}else{
    $retun_data = array("result"=>"no");
    echo json_encode($retun_data);
}

?>
       

이렇게 전부 알아보았다. 

 

게시판 관련된 강좌는 이걸로 끝이다. 사실 지금까지 공부한걸로도 왠만한 사이트는 다 만들수 있다. 물론 자바스크립트같이 프론트엔드 개발은 안했지만 서버 개발은 이정도면 충분하다.

 

다음엔 쇼핑몰을 만들어보겠다. 간단하게. 

 

반응형

+ Recent posts