Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- file upload
- Error based sql injection
- 과제
- JWT
- 로그인페이지
- 모의해킹
- cors
- Python
- sql injection
- 로그인
- 웹개발
- 쿠키
- lord of sqli
- Reflected Xss
- cookie 탈취
- Cross Site Request Forgery
- MySQL
- php
- 게시판 만들기
- XSS
- blind sql injection
- sql injection point
- Los
- union sql injection
- css
- lord of sql injection
- 세션
- csrf
- JS
- CTF
Archives
- Today
- Total
Almon Dev
게시판 만들기 #3 (게시글 목록) 본문
게시판 만들기
게시글 목록
category.js
const categories = document.querySelectorAll('.category');
categories.forEach((category) => {
category.addEventListener('click', (e) => {
const categoryId = e.target.getAttribute('data-category-id');
const categoryName = e.target.textContent;
postList(categoryId, categoryName, 1);
});
});
category 클래스를 가지고 있는 버튼을 누르면 카테고리 아이디와 카테고리 이름을 가지고 postList함수를 실행합니다.
post_list.js
function postList(categoryId, categoryName, pageNum) {
const url = '/forum/db/category.php';
const limit = 15;
const offset = (pageNum - 1) * limit;
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify({
categoryId: categoryId,
categoryName: categoryName,
limit: limit,
offset: offset,
}),
})
// .then((res) => res.text())
// .then((res) => {
// console.log(res);
// });
.then((res) => res.json())
.then((posts) => {
const postContainer = document.querySelector('.post-container');
const windowTitle = document.querySelector('.post-title');
const postContent = document.querySelector('.post-content');
const table = document.createElement('table');
table.classList.add('post-table');
const caption = document.createElement('caption');
const capSpan = document.createElement('span');
capSpan.innerHTML = '게시글 목록';
capSpan.classList.add('blind');
caption.appendChild(capSpan);
const thead = document.createElement('thead');
const idTh = document.createElement('th');
idTh.classList.add('thead-id');
idTh.textContent = '번호';
const titleTh = document.createElement('th');
const spanTh = document.createElement('span');
spanTh.textContent = '제목';
spanTh.classList.add('thead-title');
titleTh.appendChild(spanTh);
const writerTh = document.createElement('th');
writerTh.classList.add('thead-writer');
writerTh.textContent = '작성자';
const createdAtTh = document.createElement('th');
createdAtTh.classList.add('thead-date');
createdAtTh.textContent = '작성일';
const viewsTh = document.createElement('th');
viewsTh.classList.add('thead-views');
viewsTh.textContent = '조회수';
thead.appendChild(idTh);
thead.appendChild(titleTh);
thead.appendChild(writerTh);
thead.appendChild(createdAtTh);
thead.appendChild(viewsTh);
const tbody = document.createElement('tbody');
posts.forEach((post) => {
const tr = document.createElement('tr');
const idTd = document.createElement('td');
idTd.classList.add('td-id');
idTd.textContent = post.post_id;
const titleTd = document.createElement('td');
const titleWrap = document.createElement('div');
titleWrap.classList.add('td-title');
titleWrap.textContent = post.title;
titleWrap.setAttribute('data-page_num', pageNum);
titleWrap.setAttribute('data-category_id', categoryId);
titleWrap.setAttribute('data-category_name', categoryName);
titleTd.appendChild(titleWrap);
const writerTd = document.createElement('td');
writerTd.classList.add('td-writer');
writerTd.textContent = post.user_id;
const createdAtTd = document.createElement('td');
createdAtTd.classList.add('td-date');
createdAtTd.textContent = post.created_at.split(' ')[0];
const viewsTd = document.createElement('td');
viewsTd.classList.add('td-views');
viewsTd.textContent = post.views;
tr.appendChild(idTd);
tr.appendChild(titleTd);
tr.appendChild(writerTd);
tr.appendChild(createdAtTd);
tr.appendChild(viewsTd);
tbody.appendChild(tr);
});
table.appendChild(thead);
table.appendChild(tbody);
// 섹션 초기화
closePost();
windowTitle.textContent = categoryName;
// 섹션에 추가
postContent.appendChild(table);
// 페이징
paging(categoryId, categoryName, limit);
// 섹션 보이게
postContainer.classList.add('on');
readPost();
});
}
category.php에 카테고리 정보와 페이지 정보(limit, offset)를 들고 요청을 보냅니다.
응답으로 게시글의 게시글 번호, 제목, 내용, 조회수, 작성일을 받아와 태그를 생성합니다.
paging.js
function paging(categoryId, categoryName, limit) {
url = '/forum/db/paging.php';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify({
category_id: categoryId,
category_name: categoryName,
limit: limit,
}),
})
// .then((res) => res.text())
// .then((res) => console.log(res));
.then((res) => res.json())
.then((res) => {
const postContent = document.querySelector('.post-content');
const pagingTag = res.pagingTag;
console.log(pagingTag);
postContent.insertAdjacentHTML('beforeend', pagingTag);
});
}
paging.php에 카테고리 정보와 limit를 포함해 요청을 보냅니다.
postContent인 게시글 목록을 표시하고 있는 태그의 아래에 응답받은 태그를 입력합니다.
paging.php
<?php
require_once("../../mysql.php");
$result = json_decode(file_get_contents("php://input"), true) ?? null;
$category_id = $result["category_id"] ?? null;
$category_name = $result["category_name"] ?? null;
$limit = $result["limit"] ?? null;
if ($category_id) {
$sql = "select count(*) from posts where category_id=$category_id";
$postCount = runSQL($sql)->fetch_row()[0];
$pageCount = ceil($postCount / $limit);
$pageCount = $pageCount <= 1 ? 1: $pageCount;
$pagingNumTag = "";
for ($i=1; $i <= $pageCount ; $i++) {
$pagingNumTag .= "<a onclick='postList($category_id, \"$category_name\", $i)' class='paging-number'>$i</a>\n";
}
$pagingTag = "
<div class='paging-container'>
<div class='paging-prev'>
<div class='paging-prev-img'>
◁
</div>
<span class='paging-prev-text'>
이전
</span>
</div>
$pagingNumTag
<div class='paging-next'>
<span class='paging-next-text'>
다음
</span>
<div class='paging-next-img'>
▷
</div>
</div>
</div>
";
echo json_encode(["postCount" => $postCount, "pagingTag" => $pagingTag, "limit" => $limit]);
}else {
echo "fail";
}
$sql = "select count(*) from posts where category_id=$category_id";
$postCount = runSQL($sql)->fetch_row()[0];
select count를 이용해서 요청받은 카테고리에 속한 게시글의 숫자를 받아옵니다.
$pageCount = ceil($postCount / $limit);
$pageCount = $pageCount <= 1 ? 1: $pageCount;
$pagingNumTag = "";
게시글 수 / 한 페이지 숫자로 필요한 페이지 숫자를 구해줍니다. ceil은 소수점 부분이 있으면 올림 해줍니다.
삼항연산자를 이용해서 $pageCount가 1보다 작거나 같으면 1을 크면 $pageCount를 대입합니다.
for ($i=1; $i <= $pageCount ; $i++) {
$pagingNumTag .= "<a onclick='postList($category_id, \"$category_name\", $i)' class='paging-number'>$i</a>\n";
}
for문을 돌며 $pagingNumTag에 페이지 숫자를 표현할 a태그를 만듭니다.
postList(categoey_id, category_name, page_num)를 onclick 속성에 넣어서 클릭 시 페이지를 변환하도록 합니다.
echo json_encode(["postCount" => $postCount, "pagingTag" => $pagingTag, "limit" => $limit]);
만들어진 태그를 json으로 인코딩해서 응답합니다.
category.css
.post-table {
margin-top: 2rem;
width: 100%;
font-size: 13px;
table-layout: fixed;
}
th {
padding: 2px;
margin: 1px 0;
height: 45px;
color: #4e4e4e;
}
.thead-id {
width: 72px;
}
.thead-writer {
width: 118px;
}
.thead-date {
width: 80px;
}
.thead-views {
width: 68px;
}
tr {
height: 36px;
}
td {
margin-bottom: 1px;
padding: 4px 7px;
height: 36px;
text-align: center;
color: #666;
border-bottom: 1px solid rgba(200, 200, 200, 0.3);
}
.td-title {
padding-left: 30px;
text-align: left;
color: #333;
}
.td-title:hover {
text-decoration: underline;
cursor: pointer;
}
paging.css
.paging-container {
margin-top: 2rem;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
color: #333333;
}
.paging-prev,
.paging-next {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 54px;
height: 24px;
}
.paging-prev:hover,
.paging-next:hover {
cursor: pointer;
}
.paging-prev:hover .paging-prev-text,
.paging-next:hover .paging-next-text {
text-decoration: underline;
}
.paging-prev-img,
.paging-next-img {
margin-bottom: 4px;
width: 15px;
height: 20px;
}
.paging-prev-text,
.paging-next-text {
width: 26px;
height: 15px;
font-size: 13px;
}
.paging-number {
margin: 0px 2px;
padding-top: 1px;
width: 24px;
height: 24px;
text-align: center;
line-height: 24px;
font-size: 13px;
color: #333333;
}
.paging-number:hover {
cursor: pointer;
text-decoration: underline;
}
.article-info {
height: 13px;
font-size: 12px;
color: #979797;
line-height: 13px;
}
.article-date {
height: 16px;
margin-right: 8px;
}
마무리
'모의해킹 > 웹 개발' 카테고리의 다른 글
게시판 만들기 #5 (게시글 수정하기) (0) | 2024.11.12 |
---|---|
게시판 만들기 #4 (게시글 읽기) (0) | 2024.11.12 |
게시판 만들기 #2 (게시글 작성) (0) | 2024.11.11 |
게시판 만들기 #1 (0) | 2024.11.11 |
로그인 로직 구현하기(과제) (1) | 2024.11.04 |