반응형

댓글에 이미지를 첨부할 수 있도록 해보자. 댓글을 쓸때 이미지를 ajax를 이용해 첨부해서 미리보여주고 또 첨부한 이미지를 삭제할수도 있도록 수정해 보자. 우선 댓글을 쓰는 화면에 첨부 이미지를 등록할 수 있도록 작업해 보겠다.

 

/app/Views/board_view.php

 

<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 $view->subject;?></h2>
        <p class="blog-post-meta"><?php echo $view->regdate;?> by <a href="#"><?php echo $view->userid;?></a></p>

        <hr>
       
        <p>
        <?php echo $view->content;?>
        </p>
        <br>
        <?php
        if(isset($view->fs)){
          $vfs = explode(",",$view->fs);
          foreach($vfs as $img){
            if(isset($img)){
          ?>
            <img src="<?php echo  base_url('/uploads/'.$img);?>">
          <?php
            }
          }
        }?>
        <hr>
        <p style="text-align:right;">
          <?php
          if(isset($_SESSION['userid'])==$view->userid){
          ?>
          <a href="/modify/<?php echo $view->bid;?>"><button type="button" class="btn btn-primary">수정</button><a>
          <a href="/delete/<?php echo $view->bid;?>"><button type="button" class="btn btn-warning">삭제</button><a>
          <?php }?>
          <a href="/board"><button type="button" class="btn btn-primary">목록</button><a>
        </p>
      </article>
      <hr>

    <div style="margin-top:30px;">
        <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">
            <div class="btn btn-warning" id="filebutton" onclick="$('#upfile').click();">사진첨부</div>
            <input type="file" name="upfile" id="upfile" style="display:none;" />
          </div>

        </form>
    </div>

    <div id="memo_place">
      <?php
        if(isset($memoArray)){
          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">
                  <?php
                  if($ma->filename){
                  ?>
                  <img src="/uploads/<?php echo $ma->filename;?>" style="max-width:90%;">
                  <?php }?>
                  <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"><button type="button" class="btn btn-secondary btn-sm memo_reply"  mid="<?php echo $ma->memoid?>">답글</button>
                  <?php if(isset($_SESSION['userid']) and $_SESSION['userid']==$ma->userid){?>
                    <a href="javascript:;" onclick="memo_modify(<?php echo $ma->memoid?>)"><button type="button" class="btn btn-secondary btn-sm">수정</button></a>&nbsp;<a href="javascript:;" onclick="memo_del(<?php echo $ma->memoid?>)"><button type="button" class="btn btn-secondary btn-sm">삭제</button></a>
                  <?php }?>
                  </p>
                </div>
              </div>
            </div>
          </div>
         
        <?php }
        }
        ?>
    </div>

<script>
  $("#memo_button").click(function () {
        var file_table_id = $("#file_table_id").val();
        var data = {
            memo : $('#memo').val() ,
            bid : <?php echo $view->bid;?>,
            file_table_id : file_table_id
        };

        if(!data.memo){
          alert('댓글을 입력하세요.');
          return false;
        }
        $.ajax({
            async : false ,
            type : 'post' ,
            url : '/memo_write' ,
            data  : data ,
            dataType : 'html' ,
            error : function() {} ,
            success : function(return_data) {
              if(return_data=="login"){
                alert('로그인 하십시오.');
                return;
              }else if(return_data=="memo"){
                alert('댓글을 입력하세요.');
                return;
              }else{
                $('#memo').val('')
                $("#file_table_id").val('');
                $("#f_"+file_table_id).hide();
                $("#filebutton").show();
                $("#memo_place").prepend(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: '/save_image_memo',
      data: formData,
      cache: false,
      contentType: false,
      processData: false,
      dataType : 'json' ,
      type: 'POST',
      success: function (return_data) {
        if(return_data.result=='success'){
            $("#file_table_id").val(return_data.fid);
            var html = "<div class='col' id='f_"+return_data.fid+"'><div class='card h-100'><img src='/uploads/"+return_data.savename+"' class='card-img-top'><div class='card-body'><button type='button' class='btn btn-warning' onclick='memo_file_del("+return_data.fid+")'>삭제</button></div></div></div>";
            $("#upfile").hide();
            $("#filebutton").hide();
            $("#memo_image").append(html);
        }else{
          if(return_data.data=="login"){
            alert('로그인 하십시오.');
            return;
          }
        }
      }
  });
}    

function memo_file_del(fid){

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

var data = {
    fid : fid
};
    $.ajax({
        async : false ,
        type : 'post' ,
        url : '/memo_file_delete' ,
        data  : data ,
        dataType : 'json' ,
        error : function() {} ,
        success : function(return_data) {
            if(return_data.result=="no"){
                alert('삭제하지 못했습니다. 관리자에게 문의하십시오.');
                return;
            }else{
              $("#f_"+fid).hide();
              $("#file_table_id").val('');
              $("#upfile").hide();
              $("#filebutton").show();
            }
        }
});

}

</script>

기존에 올렸던 소스를 조금 수정했다. 기존에 이 파일이 있는 사람들도 위 소스로 수정해야한다. 

 

메모를 등록할때 이미지를 등록할 수 있는 사진첨부 버튼을 추가했다. 버튼을 클릭해서 이미지를 첨부하면 사전첨부 버튼이 있던 곳에 이미지가 첨부된다.

 

이렇게 된다. 아 맞다. 이미지 첨부하는 컨트롤러를 안만들었다. 만들어 보자. 우선 라우트에 등록한다.

 

/app/Config/Routes.php

 

<?php

namespace Config;

// Create a new instance of our RouteCollection class.
$routes = Services::routes();

// Load the system's routing file first, so that the app and ENVIRONMENT
// can override as needed.
if (is_file(SYSTEMPATH . 'Config/Routes.php')) {
    require SYSTEMPATH . 'Config/Routes.php';
}

/*
 * --------------------------------------------------------------------
 * Router Setup
 * --------------------------------------------------------------------
 */
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
// where controller filters or CSRF protection are bypassed.
// If you don't want to define all routes, please use the Auto Routing (Improved).
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
// $routes->setAutoRoute(false);

/*
 * --------------------------------------------------------------------
 * Route Definitions
 * --------------------------------------------------------------------
 */

// We get a performance increase by specifying the default
// route since we don't have to scan directories.

//게시판
$routes->get('/', 'Home::index');
$routes->get('/board', 'Board::list');
$routes->get('/boardWrite', 'Board::write');
$routes->match(['get', 'post'], 'writeSave', 'Board::save');
$routes->get('/boardView/(:num)', 'Board::view/$1');
$routes->get('/modify/(:num)', 'Board::modify/$1');
$routes->get('/delete/(:num)', 'Board::delete/$1');
$routes->post('/save_image', 'Board::save_image');
$routes->post('/file_delete', 'Board::file_delete');

//댓글
$routes->match(['get', 'post'], '/memo_write', 'MemoController::memo_write');
$routes->post('/save_image_memo', 'MemoController::save_image_memo');
$routes->post('/memo_file_delete', 'MemoController::memo_file_delete');

//member
$routes->get('/login', 'MemberController::login');
$routes->get('/logout', 'MemberController::logout');
$routes->match(['get', 'post'], '/loginok', 'MemberController::loginok');
/*
 * --------------------------------------------------------------------
 * Additional Routing
 * --------------------------------------------------------------------
 *
 * There will often be times that you need additional routing and you
 * need it to be able to override any defaults in this file. Environment
 * based routes is one such time. require() additional route files here
 * to make that happen.
 *
 * You will have access to the $routes object within that file without
 * needing to reload it.
 */
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
    require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}

댓글에 이미지를 추가하는 /save_image_memo 와 이미지를 삭제하는 /memo_file_delete가 추가됐다. 이제 컨트롤러를 만들어보자.

 

/app/Controllers/MemoController.php

 

<?php

namespace App\Controllers;
use App\Models\BoardModel;//사용할 모델을 반드시 써줘야한다.

class MemoController extends BaseController
{
    public function memo_write()
    {
        if(!isset($_SESSION['userid'])){
            return "login";
            exit;
        }
       
        $db = db_connect();
        $memo=$this->request->getVar('memo');
        $bid=$this->request->getVar('bid');
        $file_table_id=$this->request->getVar('file_table_id');

        $sql="INSERT INTO memo
            (bid, userid, memo, status)
            VALUES(".$bid.", '".$_SESSION['userid']."', '".$memo."', 1)";
        $rs = $db->query($sql);
        $insertid=$db->insertID();
        //error_log ('['.__FILE__.']['.__FUNCTION__.']['.__LINE__.']['.date("YmdHis").']'.print_r($file_table_id,true)."\n", 3, './php_error_'.date("Ymd").'.log');
        if(!empty($file_table_id)){//첨부한 파일이 있는 경우에만
            $uq="update file_table set bid=".$bid.", memoid=".$insertid." where fid=".$file_table_id;
            $uqs = $db->query($uq);
            $fquery="select * from file_table where status=1 and fid=".$file_table_id;
            $rs2 = $db->query($fquery);
            $imgarea = "<img src='/uploads/".$rs2->getRow()->filename."' style='max-width:90%'>";
        }else{
            $imgarea="";
        }

        $return_data = "<div class=\"card mb-4\" id=\"memo_".$insertid."\" 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\">".$imgarea."<br>".$memo."</p>
                    <p class=\"card-text\"><small class=\"text-muted\">".$_SESSION['userid']." / now</small></p>
                    <p class=\"card-text\" style=\"text-align:right\"><a href=\"javascript:;\" onclick=\"memo_modify(".$insertid.")\"><button type=\"button\" class=\"btn btn-secondary btn-sm\">수정</button></a>&nbsp;<a href=\"javascript:;\" onclick=\"memo_del(".$insertid.")\"><button type=\"button\" class=\"btn btn-secondary btn-sm\">삭제</button></a></p>
                    </div>
                </div>
                </div>
            </div>";
        return $return_data;
    }

    public function save_image_memo()
    {
        $db = db_connect();

        if(!isset($_SESSION['userid'])){
            $retun_data = array("result"=>"fail", "data"=>"login");
            return json_encode($retun_data);
            exit;
        }
       
        $file = $this->request->getFile('savefile');
            if($file->getName()){
                $filename = $file->getName();
                //$filepath = WRITEPATH. 'uploads/' . $file->store();
                $newName = $file->getRandomName();
                $filepath = $file->store('memo/', $newName);
            }

            if(isset($filepath)){
                $sql2="INSERT INTO file_table
                        (bid, userid, filename, type)
                        VALUES('', '".$_SESSION['userid']."', '".$filepath."', 'memo')";
                $rs2 = $db->query($sql2);
                $insertid=$db->insertID();                
            }

        $retun_data = array("result"=>"success", "fid"=>$insertid, "savename"=>$filepath);
        return json_encode($retun_data);
    }

    public function memo_file_delete()
    {
        $db = db_connect();
        $fid=$this->request->getVar('fid');
        $query = "select * from file_table where type='memo' and fid=".$fid;
        $rs = $db->query($query);
        if(unlink('uploads/'.$rs->getRow()->filename)){
            $query2= "delete from file_table where type='memo' and fid=".$fid;
            $rs2 = $db->query($query2);
            $retun_data = array("result"=>"ok");
            return json_encode($retun_data);
        }else{
            $retun_data = array("result"=>"no");
            return json_encode($retun_data);
        }
    }

   
}

 

save_image_memo() 함수와memo_file_delete() 함수를 추가했다. 그리고 결과값을 리턴해주면 board_view.php

에서 처리해주도록 돼 있다.

 

save_image_memo()에서는 첨부한 이미지를 저장하고 그 정보를 디비에 저장했고 memo_file_delete()에서는 반대로 해당 파일을 삭제하고 디비에서 삭제해 주었다.

 

그래서 다시 위에 댓글에 이미지를 첨부하는 화면처럼 테스트 해보자. 등록했다. 삭제하고 다시 등록해보고 했을때 제대로 작동하면 성공이다. 

 

그런 후에 댓글 등록 버튼을 클릭하면 이미지를 포함한 댓글이 저장되게 된다.

 

이렇게 보이면 성공이다. memo_write()함수에서 메모를 저장할때 첨부한 이미지가 있으면 같이 화면에 뿌려주도록 작업해 두었다. 직접 테스트해서 확인해보자.

반응형

+ Recent posts