모의해킹 스터디 4주차 과제(1) - 게시판 만들기

2024. 11. 12. 11:39·모의해킹/모의해킹 스터디

이번 과제는 게시판(CRUD)을 구현하는 과제다.

개발

우선 기본 게시판 매인화면을 만들어주었다.

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>커뮤니티</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
</head>
<body>
    <?php include '../comm/header.php'; ?>

    <main class="container">
        <div class="bg-light p-5 rounded">
            <h1>커뮤니티</h1>
            <div class="mb-3 d-grid gap-2 d-md-flex justify-content-md-end">
                <a href="create_community.php" class="btn btn-primary">게시글 등록</a>
            </div>

            <table class="table" id="data-table">
                <thead>
                    <tr>
                        <th scope="col">번호</th>
                        <th scope="col">제목</th>
                        <th scope="col">내용</th>
                        <th scope="col">작성자</th>
                        <th scope="col">작성일</th>
                    </tr>
                </thead>
                <tbody>
                    
                </tbody>
            </table>

        </div>
    </main>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

 

1. 게시판 등록

게시판을 등록하기 위해서 게시판 등록 메인 화면을 아래와 같이 만들었다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>커뮤니티 글쓰기</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">

    <style>
        a{
            text-decoration: none;
            color: white;
        }

        .text-center { 
            margin-bottom: 30px; 
        }
        .form-group { 
            margin-bottom: 10px; 
        }
        .form-group .form-control { 
            height: 45px; 
        }
        .submit-btn { 
            /* width: 100%;  */
            background-color: #70a2ee; 
            border-color: #c2d7f7; 
        }
    </style>

</head>
<body class="bg-light">
    <?php include '../comm/header.php'; ?> <!-- 헤더 포함 -->
    <main class="container">
        <div class="row justify-content-center" style="height: 100vh;">
            <div class=" my-auto">
                <h1>공지사항 글쓰기</h1>
                <form method="post" action="create_community_proc.php">
                    <div>
                        <div class="form-floating mb-3">
                            <input type="text" class="form-control" name="title" id="floatingInput" placeholder="제목을 입력해 주세요" autocomplete="off">
                            <label for="floatingInput">제목</label>
                        </div>

                        <div class="form-floating">
                            <textarea class="form-control" name="content" placeholder="내용을 입력하세요" id="floatingTextarea" style="height: 500px"></textarea>
                            <label for="floatingTextarea">내용</label>
                        </div>
                    </div>
                    </br>

                    <div class="d-grid gap-2 d-md-flex justify-content-md-end">
                        <button class="submit-btn btn btn-primary me-md-2" type="submit">글쓰기</button>
                        <button class="btn btn-secondary" type="button"><a href="community.php" >목록으로</a></button>
                    </div>
                </form>
            </div>
        </div>
    </main>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

 

그 다음 게시판 등록 로직을 개발하였다.

작성자(닉네임)는 변경 가능성을 고려하여 user_id를 저장해 게시판 조회 시 JOIN으로 작성자(닉네임)를 불러오려고 한다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결 파일

// POST로부터 데이터 가져오기
$title = $_POST['title'];
$content = $_POST['content'];
$user_id = $_SESSION['user_id'];

// 데이터베이스에 게시글 등록
$sql = "INSERT INTO community (title, content, user_id) VALUES (?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ssi", $title, $content, $user_id);

if ($stmt->execute()) {
    header("Location: community.php"); // 성공 시 메인 페이지로 리다이렉트
    exit();
} else {
    echo "게시글 등록 실패: " . $conn->error;
}

// 연결 종료
$stmt_nickname->close();
$stmt->close();
$conn->close();
?>

 

2. 게시판 조회

간단한 조회 쿼리로 메인화면에 게시판을 조회하였다.

<?php
// 데이터베이스 연결
require_once '../comm/db_connection.php'; // 데이터베이스 연결

// 게시글 조회 쿼리
$sql = "SELECT p.id, p.title, p.content, p.user_id, p.create_DT, u.nickname 
        FROM community p 
        JOIN user u ON p.user_id = u.id 
        ORDER BY p.create_DT DESC" ;
$stmt = $conn->prepare($sql);
$stmt->execute();
$result = $stmt->get_result();

?>
<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>커뮤니티</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
</head>
<body>
    <?php include '../comm/header.php'; ?> <!-- 헤더 포함 -->

    <main class="container">
        <div class="bg-light p-5 rounded">
            <h1>커뮤니티</h1>
            <div class="d-grid gap-2 d-md-flex justify-content-md-end">
                <a href="create_community.php" class="btn btn-primary">게시글 등록</a>
            </div>
            <table class="table">
                <thead>
                    <tr>
                        <th scope="col">번호</th>
                        <th scope="col">제목</th>
                        <th scope="col">내용</th>
                        <th scope="col">작성자</th>
                        <th scope="col">작성일</th>
                    </tr>
                </thead>
                <tbody>
                    <?php if ($result->num_rows > 0): ?>
                        <?php 
                        // 게시글 삽입
                        while ($row = $result->fetch_assoc()): ?>
                            <tr>
                                <th scope="row"><?php echo $row['id']; ?></th>
                                <td>
                                    <a href="view_community.php?id=<?php echo $row['id']; ?>"><?php echo htmlspecialchars($row['title']); ?></a>
                                </td>
                                <td><?php echo htmlspecialchars($row['content']); ?></td>
                                <td><?php echo htmlspecialchars($row['nickname']); ?></td>
                                <td><?php echo $row['create_DT']; ?></td>
                            </tr>
                        <?php endwhile; ?>
                    <?php else: ?>
                        <tr>
                            <td colspan="5">게시글이 없습니다.</td> <!-- 열 수에 맞춰 수정 -->
                        </tr>
                    <?php endif; ?>
                </tbody>
            </table>
        </div>
    </main>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

<?php
$stmt->close();
$conn->close();
?>

 

3. 게시판 상세 조회

게시글 ID로 상세 조회를 하는 코드를 생성하였다.

추가로 작성자 본인이 아니면 수정, 삭제 버튼이 출력이 되지 않도록 설계하였다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결 파일

// 게시글 ID 가져오기
$post_id = isset($_GET['id']) ? intval($_GET['id']) : 0;

// 게시글 조회 쿼리
$sql = "SELECT p.id, p.title, p.content, p.create_DT, p.user_id, u.nickname 
        FROM community p 
        JOIN user u ON p.user_id = u.id 
        WHERE p.id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $post_id);
$stmt->execute();
$result = $stmt->get_result();

if ($result->num_rows > 0) {
    $post = $result->fetch_assoc();
} else {
    // 게시글이 없을 경우
    header("Location: community.php"); // 게시글 목록 페이지로 리다이렉트
    exit();
}

?>

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title><?php echo htmlspecialchars($post['title']); ?> - 커뮤니티</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">

    <style>
        a{
            text-decoration: none;
            color: white;
        }

        .text-center { 
            margin-bottom: 30px; 
        }
        .form-group { 
            margin-bottom: 10px; 
        }
        .form-group .form-control { 
            height: 45px; 
        }
        .submit-btn { 
            /* width: 100%;  */
            background-color: #70a2ee; 
            border-color: #c2d7f7; 
        }
    </style>
    
</head>
<body>
    <?php include '../comm/header.php'; ?> <!-- 헤더 포함 -->
    <main class="container">
        <div class="bg-light p-5 rounded">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px;">
                <h1><?php echo htmlspecialchars($post['title']); ?></h1>
                <div style="display: flex;">
                    <p style="margin-right: 10px;"><strong>작성자:</strong> <?php echo htmlspecialchars($post['nickname']); ?></p>
                    <p><strong>작성일:</strong> <?php echo $post['create_DT']; ?></p>
                </div>
            </div>
            <div>
                <h3>내용</h3>
                <p><?php echo nl2br(htmlspecialchars($post['content'])); ?></p> <!-- 줄 바꿈 처리 -->
            </div>

            <div class="d-grid gap-2 d-md-flex justify-content-md-end">
            	<!-- 작성자 본인이 아니면 수정/삭제 불가능 -->
                <?php if ($_SESSION['user_id'] == $post['user_id']): ?>
                    <button class="submit-btn btn btn-primary me-md-2" type="button" onclick="location.href='update_community.php?id=<?php echo $post['id']; ?>'">글수정</button>
                    <button class="btn btn-danger me-md-2" type="button" onclick="if(confirm('정말 삭제하시겠습니까?')) location.href='delete_community.php?id=<?php echo $post['id']; ?>'">글삭제</button>
                <?php endif; ?>
                <button class="btn btn-secondary" type="button"><a href="community.php">목록으로</a></button>
            </div>
        </div>
    </main>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

<?php
$stmt->close();
$conn->close();
?>

 

4. 게시판 수정

수정 버튼을 누를 시 데이터를 불러오는 쿼리를 실행시킨 후 게시판 수정 메인화면을 개발하였다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결 파일

// 게시글 ID 가져오기
$post_id = isset($_GET['id']) ? intval($_GET['id']) : 0;

// 게시글 조회 쿼리
$sql = "SELECT title, content, user_id FROM community WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $post_id);
$stmt->execute();
$result = $stmt->get_result();

if ($result->num_rows > 0) {
    $post = $result->fetch_assoc();
} else {
    // 게시글이 없을 경우
    header("Location: community.php"); // 게시글 목록 페이지로 리다이렉트
    exit();
}
?>

<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>게시글 수정 - 커뮤니티</title>

    <!-- Bootstrap core CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
</head>
<body>
    <?php include '../comm/header.php'; ?> <!-- 헤더 포함 -->
    
    <main class="container">
        <div class="bg-light p-5 rounded">
            <h1>게시글 수정</h1>
            <form method="post" action="update_community_proc.php?id=<?php echo $post_id; ?>">
                <div class="mb-3">
                    <label for="title" class="form-label">제목</label>
                    <input type="text" class="form-control" id="title" name="title" value="<?php echo htmlspecialchars($post['title']); ?>" required>
                </div>
                <div class="mb-3">
                    <label for="content" class="form-label">내용</label>
                    <textarea class="form-control" id="content" name="content" rows="10" required><?php echo htmlspecialchars($post['content']); ?></textarea>
                </div>
                <button type="submit" class="btn btn-primary">수정완료</button>
                <a href="community.php" class="btn btn-secondary">취소</a>
            </form>
        </div>
    </main>

    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

<?php
$stmt->close();
$conn->close();
?>

 

게시판 수정 로직은 아래와 같이 개발하였다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결 파일

// 게시글 ID 가져오기
$post_id = isset($_GET['id']) ? intval($_GET['id']) : 0;

// POST 요청 확인
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $title = isset($_POST['title']) ? $_POST['title'] : '';
    $content = isset($_POST['content']) ? $_POST['content'] : '';

    // 게시글 업데이트 쿼리
    $sql = "UPDATE community SET title = ?, content = ? WHERE id = ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("ssi", $title, $content, $post_id);

    if ($stmt->execute()) {
        // 수정 성공 시 게시글 목록 페이지로 리다이렉트
        header("Location: community.php"); 
        exit();
    } else {
        // 수정 실패 시 에러 처리
        echo "게시글 수정에 실패했습니다.";
    }

    $stmt->close();
}

$conn->close();
?>

 

5. 게시판 삭제

게시판 삭제 로직은 아래와 같이 작성하였다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결 파일

// 게시글 ID 가져오기
$post_id = isset($_GET['id']) ? intval($_GET['id']) : 0;

// 게시글 삭제 쿼리
$sql = "DELETE FROM community WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $post_id);

if ($stmt->execute()) {
    // 삭제 성공 시 게시글 목록 페이지로 리다이렉트
    header("Location: community.php"); 
    exit();
} else {
    // 삭제 실패 시 에러 처리
    echo "게시글 삭제에 실패했습니다.";
}

$stmt->close();
$conn->close();
?>

 

6. 게시판 검색

게시판 검색은 우선 게시판 메인화면에 아래와 같이 검색 기능 코드를 추가해주었다.

 

이 전에 생성했던 PHP코드를 삭제해 주고 테이블의 <tbody> 부분은 javascript의 Ajax을 활용하여 넣으므로 삭제해 주었다.

<form method="GET" class="mb-3 d-flex justify-content-end" id="search-form">
    <div class="input-group" style="width: 50%;">
        <select name="search_field" class="form-select" style="width: auto;">
            <option value="all" <?php echo ($search_field == 'all') ? 'selected' : ''; ?>>전체</option>
            <option value="title" <?php echo ($search_field == 'title') ? 'selected' : ''; ?>>제목</option>
            <option value="content" <?php echo ($search_field == 'content') ? 'selected' : ''; ?>>내용</option>
            <option value="nickname" <?php echo ($search_field == 'nickname') ? 'selected' : ''; ?>>작성자</option>
        </select>
        <input type="text" name="search_value" class="form-control w-50" value="<?php echo htmlspecialchars($search_value); ?>" placeholder="검색어를 입력하세요">
        <select name="order" class="form-select" style="width: auto;">
            <option value="desc" <?php echo (isset($_GET['order']) && $_GET['order'] == 'desc') ? 'selected' : ''; ?>>내림차순</option>
            <option value="asc" <?php echo (isset($_GET['order']) && $_GET['order'] == 'asc') ? 'selected' : ''; ?>>오름차순</option>
        </select>
        <button class="btn btn-outline-secondary" type="submit">검색</button>
    </div>
</form>

<table class="table" id="data-table">
    <thead>
        <tr>
            <th scope="col">번호</th>
            <th scope="col">제목</th>
            <th scope="col">내용</th>
            <th scope="col">작성자</th>
            <th scope="col">작성일</th>
        </tr>
    </thead>
    <tbody>
        <!-- Ajax로 데이터 삽입. -->
    </tbody>
</table>

 

javascript에 AJAX를 활용하여 서버와의 통신을 비동기 처리를 하였다. 

더보기

비동기 처리 란? 사용자가 다른 작업을 수행하는 동안 데이터 전송이 이루어질 수 있게 하는 것으로, 페이지 전체를 새로 고치지 않고도 필요한 데이터만 로드할 수 있습니다.

$(document).ready(function() {
    // 페이지 로드 시 첫 페이지 데이터 로드
    loadPage(1);

    // 검색 폼 제출 이벤트
    $('#search-form').on('submit', function(e) {
        e.preventDefault(); // 폼 제출 방지
        loadPage(1); // 첫 페이지 데이터 로드
    });

    // Ajax를 통한 데이터 로드 함수
    function loadPage(page) {
        $.ajax({
            url: 'community_proc.php',
            type: 'GET',
            data: {
                page: page,
                search_field: $('select[name="search_field"]').val(),
                search_value: $('input[name="search_value"]').val(),
                order: $('select[name="order"]').val()
            },
            success: function(data) {
                const response = JSON.parse(data);
                $('#data-table tbody').html(response.table); // 테이블 업데이트
            }
        });
    }
});

 

그 후 아래와 같이 검색 로직을 구현해 준다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결

// 검색 기능
$search_field = $_GET['search_field'] ?? 'all'; // 기본 검색 필드
$search_value = $_GET['search_value'] ?? ''; // 검색 값 
$search_param = "%" . $search_value . "%"; 
$order = ($_GET['order'] ?? 'desc') === 'asc' ? 'ASC' : 'DESC'; // 정렬 기준 설정

// 게시글 조회 쿼리 생성
function createQuery($search_field, $search_param, $order) {
    $sql = "SELECT p.id, p.title, p.content, p.user_id, p.create_DT, u.nickname 
            FROM community p 
            JOIN user u ON p.user_id = u.id 
            WHERE 1=1";
    
    if ($search_field === 'all') {
        $sql .= " AND (p.title LIKE ? OR p.content LIKE ? OR u.nickname LIKE ?)";
    } else {
        $sql .= " AND $search_field LIKE ?";
    }

    $sql .= " ORDER BY p.create_DT $order";
    return $sql;
}

// 게시글 수 조회 쿼리 생성
function createTotalQuery($search_field) {
    $total_sql = "SELECT COUNT(*) as total FROM community p 
                  JOIN user u ON p.user_id = u.id 
                  WHERE 1=1";

    if ($search_field === 'all') {
        $total_sql .= " AND (p.title LIKE ? OR p.content LIKE ? OR u.nickname LIKE ?)";
    } else {
        $total_sql .= " AND $search_field LIKE ?";
    }

    return $total_sql;
}

// HTML 생성 함수
function generateHTML($result) {
    $tableHTML = '';
    if ($result->num_rows > 0) {
        while ($row = $result->fetch_assoc()) {
            $tableHTML .= '<tr>
                <th scope="row">' . $row['id'] . '</th>
                <td><a href="view_community.php?id=' . $row['id'] . '">' . htmlspecialchars($row['title']) . '</a></td>
                <td>' . htmlspecialchars($row['content']) . '</td>
                <td>' . htmlspecialchars($row['nickname']) . '</td>
                <td>' . $row['create_DT'] . '</td>
            </tr>';
        }
    } else {
        $tableHTML .= '<tr><td colspan="5">게시글이 없습니다.</td></tr>';
    }
    return $tableHTML;
}

// 게시글 조회
$stmt = $conn->prepare(createQuery($search_field, $search_param, $order));
if ($search_field === 'all') {
    $stmt->bind_param("sss", $search_param, $search_param, $search_param);
} else {
    $stmt->bind_param("s", $search_param);
}
$stmt->execute();
$result = $stmt->get_result();


// 결과 HTML 생성
$data = [
    'table' => generateHTML($result)
];

// JSON 형식으로 결과 반환
echo json_encode($data);
exit;

 

7. 게시판 페이지네이션

페이지네이션을 동적으로 생성하기 위해 아래의 코드를 만들어준다.

<nav aria-label="Page navigation example" id="pagination">
    <ul class="pagination justify-content-center">
        <!-- 페이지 버튼들 동적으로 추가. -->
    </ul>
</nav>

 

그 후 javascript를 아래의 코드로 변경 및 추가해 준다.

$(document).ready(function() {
    // 페이지 로드 시 첫 페이지 데이터 로드
    loadPage(1);

    // 페이지 버튼 클릭 이벤트
    $(document).on('click', '.page-link', function(e) {
        e.preventDefault(); // 기본 링크 동작 방지
        const page = $(this).data('page'); // 클릭한 버튼의 페이지 번호
        loadPage(page); // 해당 페이지 데이터 로드
    });


    // Ajax를 통한 데이터 로드 함수
    function loadPage(page) {
        $.ajax({
            url: 'community_proc.php',
            type: 'GET',
            data: {
                page: page,
                search_field: $('select[name="search_field"]').val(),
                search_value: $('input[name="search_value"]').val(),
                order: $('select[name="order"]').val()
            },
            success: function(data) {
                const response = JSON.parse(data);
                $('#data-table tbody').html(response.table); // 테이블 업데이트
                $('#pagination').html(response.pagination); // 페이징 업데이트
            }
        });
    }
});

 

마지막으로 페이징 로직을 추가/개발해주면 이번주 과제는 완성된다.

<?php
require_once '../comm/db_connection.php'; // 데이터베이스 연결

// 페이징 및 검색 설정
$limit = 10; // 한 페이지에 보여줄 게시글 수
$page = isset($_GET['page']) ? intval($_GET['page']) : 1; // 현재 페이지
$offset = ($page - 1) * $limit; // 시작 위치

// 검색 기능
$search_field = $_GET['search_field'] ?? 'all'; // 기본 검색 필드
$search_value = $_GET['search_value'] ?? ''; // 검색 값 
$search_param = "%" . $search_value . "%"; 
$order = ($_GET['order'] ?? 'desc') === 'asc' ? 'ASC' : 'DESC'; // 정렬 기준 설정

// 게시글 조회 쿼리 생성
function createQuery($search_field, $search_param, $order, $limit, $offset) {
    $sql = "SELECT p.id, p.title, p.content, p.user_id, p.create_DT, u.nickname 
            FROM community p 
            JOIN user u ON p.user_id = u.id 
            WHERE 1=1";
    
    if ($search_field === 'all') {
        $sql .= " AND (p.title LIKE ? OR p.content LIKE ? OR u.nickname LIKE ?)";
    } else {
        $sql .= " AND $search_field LIKE ?";
    }

    $sql .= " ORDER BY p.create_DT $order LIMIT ? OFFSET ?";
    return $sql;
}

// 게시글 수 조회 쿼리 생성
function createTotalQuery($search_field) {
    $total_sql = "SELECT COUNT(*) as total FROM community p 
                  JOIN user u ON p.user_id = u.id 
                  WHERE 1=1";

    if ($search_field === 'all') {
        $total_sql .= " AND (p.title LIKE ? OR p.content LIKE ? OR u.nickname LIKE ?)";
    } else {
        $total_sql .= " AND $search_field LIKE ?";
    }

    return $total_sql;
}

// HTML 생성 함수
function generateHTML($result, $total_posts, $page, $limit) {
    $tableHTML = '';
    if ($result->num_rows > 0) {
        $num = $total_posts - ($page - 1) * $limit; 
        while ($row = $result->fetch_assoc()) {
            $tableHTML .= '<tr>
                <th scope="row">' . $num-- . '</th>
                <td><a href="view_community.php?id=' . $row['id'] . '">' . htmlspecialchars($row['title']) . '</a></td>
                <td>' . htmlspecialchars($row['content']) . '</td>
                <td>' . htmlspecialchars($row['nickname']) . '</td>
                <td>' . $row['create_DT'] . '</td>
            </tr>';
        }
    } else {
        $tableHTML .= '<tr><td colspan="5">게시글이 없습니다.</td></tr>';
    }
    return $tableHTML;
}

function generatePaginationHTML($page, $total_pages) {
    $pagination = '<nav aria-label="Page navigation example"><ul class="pagination justify-content-center">';
    $start_page = max(1, $page - 2);
    $end_page = min($total_pages, $start_page + 4);

    // "<<" 버튼 추가
    if ($start_page > 1) {
        $pagination .= '<li class="page-item"><a class="page-link" href="#" data-page="1">&lt;&lt;</a></li>';
    }

    // 이전 버튼 추가
    if ($page > 1) {
        $pagination .= '<li class="page-item"><a class="page-link" href="#" data-page="' . ($page - 1) . '">이전</a></li>';
    }

    // 페이지 번호 추가
    for ($i = $start_page; $i <= $end_page; $i++) {
        $pagination .= '<li class="page-item ' . ($i === $page ? 'active' : '') . '">
            <a class="page-link" href="#" data-page="' . $i . '">' . $i . '</a>
        </li>';
    }

    // 다음 버튼 추가
    if ($page < $total_pages) {
        $pagination .= '<li class="page-item"><a class="page-link" href="#" data-page="' . ($page + 1) . '">다음</a></li>';
    }

    // ">>" 버튼 추가
    if ($end_page < $total_pages) {
        $pagination .= '<li class="page-item"><a class="page-link" href="#" data-page="' . $total_pages . '">&gt;&gt;</a></li>';
    }

    return $pagination . '</ul></nav>';
}

// 게시글 조회
$stmt = $conn->prepare(createQuery($search_field, $search_param, $order, $limit, $offset));
if ($search_field === 'all') {
    $stmt->bind_param("sssii", $search_param, $search_param, $search_param, $limit, $offset);
} else {
    $stmt->bind_param("sii", $search_param, $limit, $offset);
}
$stmt->execute();
$result = $stmt->get_result();

// 게시글 수 조회
$total_stmt = $conn->prepare(createTotalQuery($search_field));
if ($search_field === 'all') {
    $total_stmt->bind_param("sss", $search_param, $search_param, $search_param);
} else {
    $total_stmt->bind_param("s", $search_param);
}
$total_stmt->execute();
$total_result = $total_stmt->get_result();
$total_row = $total_result->fetch_assoc();
$total_posts = $total_row['total'];
$total_pages = ceil($total_posts / $limit);

// 결과 HTML 생성
$data = [
    'table' => generateHTML($result, $total_posts, $page, $limit),
    'pagination' => generatePaginationHTML($page, $total_pages)
];

// JSON 형식으로 결과 반환
echo json_encode($data);
exit;

 

결과

1. 게시판 등록

게시판 등록

2. 게시판 조회

게시판 조회

3. 게시판 상세 조회

  • 본인 작성

본인이 작성한 글

  • 타인 작성

타인이 작성한 글

4. 게시판 수정

게시판 수정

5. 게시판 삭제

게시판 삭제

6. 게시판 검색

게시판 검색

7. 게시판 페이지네이션

게시판 페이징

후기

  • 이제 PHP가 어느 정도 익숙해진 것 같다.
  • 보안 측면인 부분에서 추가로 필요한 사항이 어떤 게 있는지 고려해 봐야겠다.
728x90
반응형
저작자표시 비영리 동일조건 (새창열림)

'모의해킹 > 모의해킹 스터디' 카테고리의 다른 글

모의해킹 스터디 5주차 정리  (0) 2024.11.15
모의해킹 스터디 4주차 과제(2) - 쿠키 탈취 / 키로거  (0) 2024.11.14
모의해킹 스터디 4주차 정리  (0) 2024.11.08
모의해킹 스터디 3주차 과제(2) - 리눅스 환경에서 PHP로 JWT 구현  (0) 2024.11.06
모의해킹 스터디 3주차 과제(1) - 로그인 케이스 구현  (0) 2024.11.01
'모의해킹/모의해킹 스터디' 카테고리의 다른 글
  • 모의해킹 스터디 5주차 정리
  • 모의해킹 스터디 4주차 과제(2) - 쿠키 탈취 / 키로거
  • 모의해킹 스터디 4주차 정리
  • 모의해킹 스터디 3주차 과제(2) - 리눅스 환경에서 PHP로 JWT 구현
BPM37093
BPM37093
luna의 IT기술 정리
  • BPM37093
    IT Study Log
    BPM37093
  • 링크

  • 글쓰기 관리
    • 분류 전체보기 (43)
      • 모의해킹 (37)
        • 웹해킹 (1)
        • 모의해킹 스터디 (36)
      • Web (5)
        • 웹 보안 (1)
        • 웹 크롤링 (1)
      • Data (0)
      • Cloud (0)
      • Network (1)
  • 인기 글

  • 방문자 수

    방문자수Total

    • Today :
  • 태그

    NAT
    오블완
    httprequest
    Chrome
    WEB
    웹해킹
    웹개발
    burpsuite
    php
    javascript
    상태코드
    SQL
    메서드
    티스토리챌린지
    Network
    sqlinjection
    HttpResponse
    HTML
    HTTP
    hash
    모의해킹스터디
    mysql
  • hELLO· Designed By정상우.v4.10.1
BPM37093
모의해킹 스터디 4주차 과제(1) - 게시판 만들기
상단으로

티스토리툴바