KnockOn

[3주차 TIL] KnockOn Bootcamp PHP 게시판 수정 및 삭제

성밍쟁 2024. 12. 22. 23:39
728x90
반응형

프롤로그

저번 글에서는 게시판 생성 및 조회를 진행했었다.

2024.12.22 - [KnockOn] - [3주차 TIL] KnockOn Bootcamp PHP 게시판 생성 및 조회

 

[3주차 TIL] KnockOn Bootcamp PHP 게시판 생성 및 조회

프롤로그저번 글2024.12.22 - [분류 전체보기] - [3주차 TIL] KnockOn Bootcamp PHP와 MySQL 연결, 회원가입과 로그인 [3주차 TIL] KnockOn Bootcamp PHP와 MySQL 연결, 회원가입과 로그인프롤로그이제 진짜로 php와 MySQL

taesan-smj.tistory.com

CRUD 중에서 Create 와 Read를 진행한 것이다.

이제 Update와 Delete를 진행할 것이다.

 

진행중인 코드는

https://github.com/Vak-kas/php/tree/board

 

GitHub - Vak-kas/php: knockon 웹 모의해킹 코스

knockon 웹 모의해킹 코스. Contribute to Vak-kas/php development by creating an account on GitHub.

github.com

여기서 확인할 수 있다.

 

 

 

view.php수정

수정을 하기 위해서 수정버튼과 삭제버튼이 있어야 하기에, view.php에다가 버튼 두 개만 추가하겠다.

<?php
// session_start();
require('../databases.php');
include('../base.php'); 
?>

<?php
$post_id = isset($_GET['id']) ? $_GET['id'] : 0;
$sql = "SELECT * FROM posts WHERE id = $post_id";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    $post = $result->fetch_assoc();
    $new_view_count = $post['view_count'] + 1;
    $update_sql = "UPDATE posts SET view_count = $new_view_count WHERE id = $post_id";
    $conn->query($update_sql);
} else {
    echo "<script>alert('존재하지 않는 게시글입니다.'); window.location.href = '/board/board.php';</script>";
    exit();
}
?>

<link rel="stylesheet" type="text/css" href="/static/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="write.css">

<div class="container my-3">
    <h5 class="border-bottom py-2"><?php echo $post['title']; ?></h5>
    <div class="card my-3">
        <div class="card-body">
            <div class="card-text" style="white-space: pre-line;"><?php echo nl2br($post['content']); ?></div>
            <div class="d-flex justify-content-end">
                <div class="badge bg-light text-dark p-2">
                    <div class="mb-2">
                        <?php echo $post['author']; ?>
                    </div>
                    <?php echo $post['created_at']; ?>
                </div>
            </div>
        </div>
    </div>
    <div>
        <?php if (!empty($post['attachment'])): ?>
            <h5>첨부파일</h5>
            <?php 
                // 파일 이름을 추출
                $file_name = basename($post['attachment']); 
            ?>
            <a href="<?php echo $post['attachment']; ?>" class="btn btn-link" download="<?php echo $file_name; ?>">
                <?php echo $file_name; ?> 다운로드
            </a>
        <?php else: ?>
            <p>첨부파일이 없습니다.</p>
        <?php endif; ?>
    </div>
    <div>
    <?php if ($post['author'] == $_SESSION['username']): ?>
        <form action="edit.php" method="get" style="display:inline;">
            <input type="hidden" name="id" value="<?php echo $post['id']; ?>">
            <button type="submit" class="btn btn-warning">수정하기</button>
        </form>
        <form action="delete.php" method="post" style="display:inline;">
            <input type="hidden" name="id" value="<?php echo $post['id']; ?>">
            <button type="submit" class="btn btn-danger" onclick="return confirm('정말 삭제하시겠습니까?')">삭제하기</button>
        </form>
    <?php endif; ?>
    </div>
    <br>
    <div>
        <form action="board.php" method="get">
            <button type="submit" class="btn btn-primary">목록으로 돌아가기</button>
        </form>
    </div>
</div>




</body>
</html>

<?php
// 데이터베이스 연결 종료
$conn->close();
?>

밑에줄에

    <div>
    <?php if ($post['author'] == $_SESSION['username']): ?>
        <form action="edit.php" method="get" style="display:inline;">
            <input type="hidden" name="id" value="<?php echo $post['id']; ?>">
            <button type="submit" class="btn btn-warning">수정하기</button>
        </form>
        <form action="delete.php" method="post" style="display:inline;">
            <input type="hidden" name="id" value="<?php echo $post['id']; ?>">
            <button type="submit" class="btn btn-danger" onclick="return confirm('정말 삭제하시겠습니까?')">삭제하기</button>
        </form>
    <?php endif; ?>
    </div>
    <br>

여기가 추가 된 거다. 버튼 두 개가 만들어진 것이다.

그리고 hidden input도 하나 넣어주었다. 저거 없어서 자꾸 수정이 안 되었는데, 저거떄문에;;;; 아이디값이 안 넘겨졌다.;;;

보면, 수정 버튼을 눌렀을 때는 edit.php로 넘어가게 해놨고, 삭제 버튼을 눌렀을 때는 delete.php로 넘어가게 해놨다. 

그리고, php if문을 보면 현재 로그인된 사용자와 글의 작성자가 일치하는 경우를 확인하였다.

 

 

 

 

삭제하기 코드 작성

수정하기는 좀 어려울 수 있으니, 삭제하기 부터 진행할 것이다.

여기서부터 다시 맥북으로 작업하기에 일부분 조금 코드 바뀔 수 있다.

[특히, session_start() 이부분에서 오류 많이 나서 웬만한 부분 그냥 다 주석처리함]

삭제를 한다면, 데이터 자체를 삭제하는 것이다. 

우리에게 주어져있는 건, id가 주어질 테니

delete from posts where id = $_POST['id'];

를 쿼리문으로 날린다면 삭제가 될 것이다.

다만 혹시 몰라서, 로그인된 사람이랑 작성자가 일치하는지도 보기 위해서, 

delete.php를 이렇게 작성하자.

<?php
session_start();
require('../databases.php'); 


if (!isset($_SESSION['username'])) {
    header("Location: /login/login.html");
    exit();
}


$post_id = isset($_POST['id']) ? $_POST['id'] : 0;

if ($post_id > 0) {
    $sql = "DELETE FROM posts WHERE id = $post_id AND author = '" . $_SESSION['username'] . "'";

    if ($conn->query($sql) === TRUE) {
        echo "<script>
                alert('게시글이 삭제되었습니다.');
                window.location.href = '/board/board.php';
              </script>";
    } else {
        echo "<script>
                alert('게시글 삭제에 실패했습니다. 다시 시도해주세요.');
                window.location.href = '/board/board.php';
              </script>";
    }
} else {
    echo "<script>
            alert('잘못된 요청입니다.');
            window.location.href = '/board/board.php';
          </script>";
}

$conn->close();
?>

코드를 짜고 실행을 시켜보면

진짜 삭제하겠습니까? 뜨고

글이 삭제가 된 것을 확인할 수 있다. 

데이터베이스를 확인해볼까?

잘 삭제된 것을 확인할 수 있다.

 

 

 

수정하기 페이지 작성

수정하기버튼을 눌렀을 때, 보통 게시판 에다가 자신이 썼던 글이 그대로 있어야 하기에, write.php그대로 일단은 들고 올 것이다.

edit.php를 만들고, 기존 write.php 코드에다가, 이제 내용부분에다가 기존 글들을 불러와서 넣어주기만 하면 된다.

우선 edit.php를 작성하자

<?php
// session_start();
require('../databases.php'); 
include('../base.php');
?>

<?php
$post_id = isset($_GET['id']) ? $_GET['id'] : 0;
$sql = "SELECT * FROM posts WHERE id = $post_id";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    $post = $result->fetch_assoc();
} else {
    echo "<script>alert('존재하지 않는 게시글입니다.'); window.location.href = '/board/board.php';</script>";
    exit();
}
?>



<link rel="stylesheet" type="text/css" href="/static/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="write.css">

<div class="container">
    <h2 class="my-3">게시글 수정</h2>
    <form action="edit_process.php" method="post" enctype="multipart/form-data">
        <input type="hidden" name="id" value="<?php echo $post['id']; ?>">
        
        <div class="mb-3">
            <label for="title" class="form-label"><h5>제목</h5></label>
            <input type="text" class="form-control" name="title" id="title" value="<?php echo $post['title']; ?>" required>
        </div>
        
        <div class="mb-3">
            <label for="content" class="form-label"><h5>내용</h5></label>
            <textarea class="form-control" name="content" id="content" rows="10" required><?php echo $post['content']; ?></textarea>
        </div>

        <div class="mb-3">
            <label for="attachment" class="form-label"><h5>첨부파일</h5></label>
            <input type="file" class="form-control" name="attachment" id="attachment">
            <?php 
                // 파일 이름을 추출
                $file_name = basename($post['attachment']); 
            ?>
            <?php if ($post['attachment']): ?>
                <p>현재 첨부파일: <a href="<?php echo $post['attachment']; ?>" download><?php echo $file_name; ?> 다운로드</a></p>
            <?php endif; ?>
        </div>
        <div>
    </div>

        <button type="submit" class="btn btn-primary">수정하기</button>
    </form>
</div>

</body>
</html>

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

아까랑 똑같다. 내용은, 

다만 맨 윗줄에 

<?php
// session_start();
require('../databases.php'); 
include('../base.php');
?>

<?php
$post_id = isset($_GET['id']) ? $_GET['id'] : 0;
$sql = "SELECT * FROM posts WHERE id = $post_id";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    $post = $result->fetch_assoc();
} else {
    echo "<script>alert('존재하지 않는 게시글입니다.'); window.location.href = '/board/board.php';</script>";
    exit();
}
?>

여기 보면, 

post id로 해당 글 내용 불러오는 코드가 있고, 각 내용들을 채워넣어주었다.

실행시키면

여기서 수정하기 버튼을 클릭하면

현재 글 정보가 그대로 남아있는 것을 알 수 있다.

 

 

 

수정 처리 코드 작성하기

이제 수정하는 것만 작성하면 된다.

<form action="edit_process.php" method="post" enctype="multipart/form-data">

로 해놨기 때문에, edit_process.php를 만들고 아래와 같이 코드를 작성하였다.

<?php
session_start();
require('../databases.php'); 

if (!isset($_SESSION['username'])) {
    header("Location: /login/login.html");
    exit();
}

$post_id = isset($_POST['id']) ? $_POST['id'] : 0;
$title = $_POST['title'];
$content = $_POST['content'];
$attachment = null;

if (empty($title) || empty($content)) {
    echo "<script>alert('제목과 내용은 필수 항목입니다.'); window.location.href = 'edit.php?id=$post_id';</script>";
    exit();
}

// 첨부파일 처리
if (isset($_FILES['attachment']) && $_FILES['attachment']['error'] == 0) {
    $upload_dir = '../uploads/board/';
    $file_name = basename($_FILES['attachment']['name']);
    $timestamp = time();
    $new_file_name = $file_name . "_" . $timestamp ;
    $file_path = $upload_dir . $new_file_name;

    if (move_uploaded_file($_FILES['attachment']['tmp_name'], $file_path)) {
        $attachment = $file_path;
    } else {
        echo "<script>alert('파일 업로드에 실패했습니다.'); window.location.href = 'edit.php?id=$post_id';</script>";
        exit();
    }
}
$update_sql = "UPDATE posts SET title = '$title', content = '$content', attachment = '$attachment' WHERE id = $post_id AND author = '" . $_SESSION['username'] . "'";

if ($conn->query($update_sql) === TRUE) {
    echo "<script>
            alert('게시글이 수정되었습니다.');
            window.location.href = '/board/view.php?id=$post_id';
          </script>";
} else {
    echo "<script>
            alert('게시글 수정에 실패했습니다. 다시 시도해주세요.');
            window.location.href = 'edit.php?id=$post_id';
          </script>";
}

$conn->close();
?>

다 똑같고, update_sql 에다가 UPDATE 처리하는 쿼리 넣은 것이 다이다.

이렇게 바꾸고 수정하기 버튼을 클릭하면

이렇게 뜨면서

게시판으로 넘어왔다.

e

데이터베이스도 잘 수정이 된 것을 확인할 수 있다.

 

 

에필로그

아이디 중복 검사, 비밀번호 해쉬, SQL인젝션 방지, 세션 쿠키 만료시간 설정

파일 용량 크기 제한 풀기 해야함

다음으로 해야할 것은 이제 게시글 검색 기능이다.

728x90
반응형