8.15. 목록 화면 만들기
메모를 쓰고 목록을 확인하고 삭제할 수 있는 페이지를 만든다.
<?php
// 로그인 체크
session_start();
if (isset($_SESSION['member_id']) === false){
header("Location: /");
exit();
}
// DB Require
require_once("inc/db.php");
$member_id = $_SESSION['member_id'];
$post_query = "select post_id, post_content from tbl_post where member_id = ? order by insert_date desc limit 10";
$post_data = db_select($post_query, array($member_id));
$last_post_id = count($post_data) > 0 ? $post_data[count($post_data) - 1]['post_id'] : "0";
?>
<!DOCTYPE html>
<html>
<head>
<title>php-memo 목록</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script type="text/javascript">
function post_delete(post_id){
$.post("/delete.api.php", {'post_id' : post_id})
.done(function(result){
if (result['result']){
alert('삭제되었습니다.');
$('#post_' + post_id).remove();
}
});
}
function next_list(){
var last_post_id = $('#last_post_id').val();
$.post("/list.api.php", {'last_post_id' : last_post_id})
.done(function(result){
if (result['result'] == false){
alert('글을 불러오는 데 실패했습니다.');
return;
}
if (result['post_data'].length == 0){
alert("더이상 글이 없습니다.");
return;
}
var ul_list_data = $('#ul_list_data');
for (var i=0;i<result['post_data'].length;i++) {
var post = result['post_data'][i];
var append_li = '<li id="post_' + post['post_id'] + '">"';
append_li += post['post_content'];
append_li += '<input type="button" value="삭제" onclick="post_delete(\'' + post['post_id'] + '\');return false;" />';
append_li += "</li>";
ul_list_data.append(append_li);
$('#last_post_id').val(post['post_id']);
}
});
}
</script>
</head>
<body>
<?php require_once("inc/header.php"); ?>
<h1>php-memo 목록</h1>
<form method="POST" action="write.post.php">
<p>
<input type="text" id="post_content" name="post_content" style="width:100%" />
</p>
<p>
<input type="submit" id="post_write" value="글 저장" />
</p>
</form>
<ul id='ul_list_data'>
<?php
foreach($post_data as $post){
?>
<li id="post_<?= $post['post_id'] ?>">
<?= $post['post_content'] ?>
<input type="button" value="삭제" onclick="post_delete('<?= $post['post_id'] ?>');return false;" />
</li>
<?php
}
?>
</ul>
<a href="#" id='more' onclick="next_list();">더보기</a>
<input type='hidden' id='last_post_id' value="<?php echo $last_post_id ?>" />
</body>
</html>
위 코드를 list.php 파일로 저장한다.
목록 페이지는 본인의 것만 볼 수 있으므로 로그인되어 있는지 확인한다.
// 로그인 체크
session_start();
if (isset($_SESSION['member_id']) === false){
header("Location: /");
exit();
}
세션에서 현재 로그인된 사용자의 PK를 가지고 온다.
$member_id = $_SESSION['member_id'];
글 쓰기 폼을 만든다. 이 폼은 write.post.php 페이지를 HTML Form을 이용한 POST 방식으로 호출한다.
<form method="POST" action="write.post.php">
<p>
<input type="text" id="post_content" name="post_content" style="width:100%" />
</p>
<p>
<input type="submit" id="post_write" value="글 저장" />
</p>
</form>
처음 페이지가 보여질 때 최신 메모 목록을 보여줘야 한다. 이를 위해 현재 로그인한 사용자의 최근 글 10개를 데이터베이스에서 가지고 온다.
$post_query = "select post_id, post_content from tbl_post where member_id = ? order by insert_date desc limit 10";
$post_data = db_select($post_query, array($member_id));
최신 메모 목록을 화면에 보여준다.
<ul id='ul_list_data'>
<?php
foreach($post_data as $post){
?>
<li id="post_<?= $post['post_id'] ?>">
<?= $post['post_content'] ?>
<input type="button" value="삭제" onclick="post_delete('<?= $post['post_id'] ?>');return false;" />
</li>
<?php
}
?>
</ul>
메모 목록을 foreach 구문으로 하나씩 반복한다.
foreach($post_data as $post)
HTML에서 id는 항목을 구별하는 식별자다. 각 메모마다 post_ 문자열 + tbl_post.post_id 값을 붙여 유일한 HTML 식별자를 만들어낸다. 이 식별자는 개별 글 삭제 기능 구현에 쓰인다.
<li id="post_<?= $post['post_id'] ?>">
이 코드가 html에서 보일 때는 이렇게 보여진다.
<li id="post_6">
<?= 는 <?php echo 와 같은 뜻이다. 곧바로 다음에 나오는 내용을 출력한다.
<?= $post['post_content'] ?>
위 코드는 데이터베이스에 저장된 메모 내용을 출력한다.
개별 글 삭제 기능 호출하기
개별 글 삭제는 HTML Form 방식이 아니라 Ajax를 이용해 비동기로 처리한다. 따라서 화면 깜박임 없이 기능 처리가 가능하다.
Ajax 기능을 편하게 이용하기 위해 jQuery라는 자바스크립트 라이브러리를 사용할 것이다.
jQueryCDN https://code.jquery.com/ 에서 jQuery를 불러온다. 참고로 CDN은 Content Delivery Network의 약자로 정적인 컨텐츠를 빠르게 불러오기 위해 모아놓은 웹 저장소라고 이해하면 편하다.
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
자바스크립트 영역을 시작한다. 자바스크립트는 클라이언트, 즉 웹 브라우저에서 실행되는 프로그래밍 언어다.
<script type="text/javascript">
비동기로 글을 삭제하는 글 삭제 API를 호출하는 함수를 만든다. 글 삭제 API 의 주소는 /delete.api.php다.
function post_delete(post_id){
$.post("/delete.api.php", {'post_id' : post_id})
.done(function(result){
if (result['result']){
alert('삭제되었습니다.');
$('#post_' + post_id).remove();
}
});
}
($.post) 코드로 POST 메소드를 이용해서 /delete.api.php 페이지를 호출한다. 이 때 파라미터 이름과 값은 {'post_id' : post_id} 이다.
$.post("/delete.api.php", {'post_id' : post_id})
정상적으로 서버가 값을 리턴하면 리턴한 결과가 result 변수에 담긴다.
.done(function(result){
result.result == true 이면 삭제되었다는 알림을 보낸다.
if (result['result']){
alert('삭제되었습니다.');
html에서도 글이 삭제되었다는 것을 표시해야 하므로 HTML ID로 글 항목을 찾아 삭제한다.
$('#post_' + post_id).remove();
자바스크립트 영역을 닫을 때는 </script> 로 표기한다.
</script>
글 삭제 함수를 호출하는 HTML 버튼을 그린다.
<input type="button" value="삭제" onclick="post_delete('<?= $post['post_id'] ?>');return false;" />
위 코드가 HTML로 표현되면 아래와 같다.
<input type="button" value="삭제" onclick="post_delete('6');return false;" />
더보기 기능 넣기
더보기 버튼을 클릭하면 현재 html에 렌더링된 항목보다 오래된 글을 서버에서 비동기로 가지고 온다.
이 기능을 구현하기 위해서는 현재 HTML에 렌더링된 마지막 메모가 무엇인지 클라이언트가 알고 있어야 한다.
페이지가 처음 렌더링될 때 마지막 메모 PK를 가지고 온다.
$last_post_id = count($post_data) > 0 ? $post_data[count($post_data) - 1]['post_id'] : "0";
마지막 메모 ID는 글이 0개 초과일 경우 배열의 마지막 항목($post_data[count($post_data) - 1]) 의 post_id 이며, 글이 0개일 때는 0이다. tbl_post.post_id 는 UNSIGNED BIGINT 타입이므로 1보다 작은 수는 없기 때문에 가장 작은 값으로 설정하는 것이다.
마지막 메모 ID는 보이지 않는 숨김 태그에 넣어둔다.
<input type='hidden' id='last_post_id' value="<?php echo $last_post_id ?>" />
더보기 버튼을 클릭했을 경우 글 목록 API를 호출하는 함수를 만든다. 글 목록 API 주소는 list.api.php 이며 파라미터는 last_post_id다.
function next_list(){
var last_post_id = $('#last_post_id').val();
$.post("/list.api.php", {'last_post_id' : last_post_id})
.done(function(result){
if (result['result'] == false){
alert('글을 불러오는 데 실패했습니다.');
return;
}
if (result['post_data'].length == 0){
alert("더이상 글이 없습니다.");
return;
}
var ul_list_data = $('#ul_list_data');
for (var i=0;i<result['post_data'].length;i++) {
var post = result['post_data'][i];
var append_li = '<li id="post_' + post['post_id'] + '">"';
append_li += post['post_content'];
append_li += '<input type="button" value="삭제" onclick="post_delete(\'' + post['post_id'] + '\');return false;" />';
append_li += "</li>";
ul_list_data.append(append_li);
$('#last_post_id').val(post['post_id']);
}
});
}
숨김 태그에 설정된 마지막 메모 ID를 읽어들인다.
var last_post_id = $('#last_post_id').val();
더보기 데이터를 서버에 비동기로 요청한다.
$.post("/list.api.php", {'last_post_id' : last_post_id})
더이상 불러올 데이터가 없을 경우 알림창을 보여준다.
if (result['post_data'].length == 0){
alert("더이상 글이 없습니다.");
return;
}
서버에서 반환한 JSON 데이터로 목록에 HTML을 추가한다.
var ul_list_data = $('#ul_list_data');
for (var i=0;i<result['post_data'].length;i++) {
var post = result['post_data'][i];
var append_li = '<li id="post_' + post['post_id'] + '">"';
append_li += post['post_content'];
append_li += '<input type="button" value="삭제" onclick="post_delete(\'' + post['post_id'] + '\');return false;" />';
append_li += "</li>";
ul_list_data.append(append_li);
$('#last_post_id').val(post['post_id']);
}
참고로 위 자바스크립트 코드는 아래의 PHP 코드와 동일한 HTML을 그린다.
<?php
foreach($post_data as $post){
?>
<li id="post_<?= $post['post_id'] ?>">
<?= $post['post_content'] ?>
<input type="button" value="삭제" onclick="post_delete('<?= $post['post_id'] ?>');return false;" />
</li>
<?php
}
?>