벌써 웹 개발의 마지막 포스팅이다
마지막으로 구현해볼 것은 비회원도 이용할 수 있는 문의 게시판이다
비회원도 이용할 수 있기 때문에 비밀번호로 게시글을 잠금할 수 있는 기능을 만들어볼 것이다
qna_write.php
<?php
//비회원도 이용가능해야하므로 세션없어도 이용가능해야함
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>문의 게시판 글쓰기</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
<?php
require('./nav.html');
?>
<style>
#boardwrite{
margin:0 auto;
}
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<BR>
<h1>문의 게시판 글쓰기</h1>
<HR>
<form action="./qna_write_proc.php" method="POST" enctype="multipart/form-data">
<table id="boardwrite">
<thead>
<tr>
<th>제목</th>
<td class="title"><input style="width:700px;" type="text" name="bTitle" id="bTitle"></td>
</tr>
<tr>
<th>내용</th>
<td class="content"><textarea style="width:700px;height:400px;" name="bContent" id="bContent"></textarea></td>
</tr>
<tr>
<th>전화번호</th>
<td class="phone"><input placeholder="비밀글로 하시려면 작성해주세요" style="width:700px;" type="text" name="bPhone" id="bPhone"></td>
</tr>
<tr>
<th></th>
<td>
<!-- 게시글 잠금 기능 -->
<input type="checkbox" value="1" name="lockpost" id="lockpost"/> 비밀글 설정
</td>
</tr>
</thead>
<tbody>
<tr>
<th></th>
<td>
<input type="file" name="board_file" />
<a href="qna_board.php" class="btnLIst btn"><div style="margin-left:300px;border:2px solid grey;">목록</div></a>
<button
style="background-color:pink"
type="submit"
onClick=
"return confirm('이대로 작성하시겠습니까? \n전화번호를 남기셨으면 차후 전화번호인증을 통해 게시글을 열람할 수 있습니다.')">
<div class="btnSEt">작성</div>
</button>
</td>
</tr>
</tbody>
</form>
</body>
</html>
자유 게시판과의 차이점은 전화번호를 넣는 칸이 생겼고 비밀글 설정 버튼이 추가되었다는 점이다
이 전화번호를 통해 비밀글을 열람할 수 있다
비밀글 설정 체크박스를 체크하면 lock_post라는 문의 게시판db 컬럼에 저장한다
$lockpost는 잠겼을 때 1, 열렸을 때 0이다
작성 버튼을 누르면 작성한 값을 qna_write_proc.php로 전송한다
qna_write_proc.php
<?php
//세션 시작
session_start();
//작성된 값을 받아서 변수로 저장함
if(isset($_SESSION['id'])){
$name = $_SESSION['id'];
} else {
$name = "익명";
}
$bPhone = $_POST['bPhone'];
$bTitle = $_POST['bTitle'];
// $bNick = $_POST['bNick'];
echo $_POST['lockpost'];
$date = date('Y-m-d');
$bContent = $_POST['bContent'];
if(isset($_POST['lockpost'])){
$lock_post = 1 ;
} else {
$lock_post = 0 ;
}
//파일 관련 변수
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_FILES['board_file'])){
// $filesize=$_FILES['board_file']['size'];
// $file_error=$_FILES['board_file']['error'];
$tmpfile = $_FILES['board_file']['tmp_name'];
$origin_filename = $_FILES['board_file']['name'];
$allowed_mime_types =['image/jpeg','image/png','image/gif','application/zip','application/x-hwp','application/msword','application/pdf']; //mime허락된 형식
$filename = iconv("UTF-8","EUC-KR",$_FILES['board_file']['name']);
$timestamp = time();
$new_filename = $timestamp.'_'.$filename;
$file_mime_type = mime_content_type($tmpfile);
// if(in_array($file_mime_type, $allowed_mime_types)){
//파일 저장 경로
$upload_path = './upload/'.$new_filename;
if(move_uploaded_file($tmpfile,$upload_path)){
$_SESSION['write_error'] = '파일 업로드 success!';
} else {
$_SESSION['write_error'] = '파일 업로드 Fail ㅜㅜ';
}
} else {
};
//데이터베이스에 저장할 쿼리 엶
$con = mysqli_connect('localhost','root','1234','test');
if(!empty($origin_filename)){
$query = "INSERT INTO qna_board (title, content, date, name,phone,file,lock_post) VALUES ('$bTitle','$bContent','$date','$name','$bPhone','$new_filename','$lock_post')";
} else {
$query = "INSERT INTO qna_board (title, content, date, name,phone,file,lock_post) VALUES ('$bTitle','$bContent','$date','$name','$bPhone',NULL,'$lock_post')";
}
if ($con->query($query)){
echo "<h1>글쓰기 완료</h1>";
echo "<p>작성한 글이 성공적으로 등록되었습니다.</p>";
echo "<a href='qna_board.php'><button>목록으로 돌아가기</button></a>";
} else {
echo "Error:".$sql."<br>".mysqli_error($con);
echo "<a href='qna_write.php'><button>돌아가기</button></a>";
}
?>
동시에 qna_modify.php도 수정해준다
qna_write.php와 비슷하지만 수정하는 창에 맞게 단어를 바꾸면 된다
qna_modify.php 일부
<h1>문의 게시판 글수정</h1>
<hr>
<div id="boardwrite">
<h6>문의게시판 글수정</h6>
<br>
<form action="./qna_modify_proc.php?number=<?php echo $bno; ?>" method="POST" enctype="multipart/form-data">
<table id="boardwrite">
<thead>
<tr>
<th>제목</th>
<td class="title"><input style="width:700px;" type="text" name="bTitle" id="bTitle"></td>
</tr>
<tr>
<th>내용</th>
<td class="content"><textarea style="width:700px;height:400px;" name="bContent" id="bContent"></textarea></td>
</tr>
<tr>
<th>전화번호</th>
<td class="phone"><input placeholder="비밀글로 하시려면 작성해주세요" style="width:700px;" type="text" name="bPhone" id="bPhone"></td>
</tr>
<tr>
<th></th>
<td>
<!-- 게시글 잠금 기능 -->
<input type="checkbox" value="1" name="lockpost" id="lockpost"/> 비밀글 설정
</td>
</tr>
</thead>
<tbody>
<tr>
<th></th>
<td>
<input type="file" name="board_file" />
<a href="qna_board.php" class="btnLIst btn"><div style="margin-left:300px;border:2px solid grey;">목록</div></a>
<button
style="background-color:pink"
type="submit"
onClick=
"return confirm('이대로 작성하시겠습니까? \n전화번호를 남기셨으면 차후 전화번호인증을 통해 게시글을 열람할 수 있습니다.')">
<div class="btnSEt">작성</div>
</button>
</td>
</tr>
</tbody>
</table>
<br>
<div class="btnSEt">
<button type="submit" class="btnSubmit btn">수정 완료</button>
<a href="./qna_board.php" class="btnLIst btn">목록</a></div>
</form>
qna_modify에서 수정완료를 누르면 qna_modify_proc.php로 페이지 이동 후 완료한다
qna_modify_proc.php
<?php
session_start();
$con = mysqli_connect('localhost','root','1234','test');
//이 부분은 url로 전달받음
$bno = $_GET['number'];
//이건 로그인한 이후로 원래 있는거
if(isset($_SESSION['id'])){
$username = $_SESSION['id'];
} else {
$username = "익명";
}
//post로 전달받은 부분
$bPhone = $_POST['bPhone'];
$bTitle = $_POST['bTitle'];
$bContent = $_POST['bContent'];
if(isset($_POST['lockpost'])){
$lock_post = 1 ;
} else {
$lock_post = 0 ;
}
//파일 관련 변수
if($_SERVER['REQUEST_METHOD'] == 'POST' && !empty($_FILES['board_file'])){
// $filesize=$_FILES['board_file']['size'];
// $file_error=$_FILES['board_file']['error'];
$tmpfile = $_FILES['board_file']['tmp_name'];
$origin_filename = $_FILES['board_file']['name'];
$allowed_mime_types =['image/jpeg','image/png','image/gif','application/zip','application/x-hwp','application/msword','application/pdf']; //mime허락된 형식
$filename = iconv("UTF-8","EUC-KR",$_FILES['board_file']['name']);
$timestamp = time();
$new_filename = $timestamp.'_'.$filename;
$file_mime_type = mime_content_type($tmpfile);
// if(in_array($file_mime_type, $allowed_mime_types)){
//파일 저장 경로
$upload_path = './upload/'.$new_filename;
if(move_uploaded_file($tmpfile,$upload_path)){
$_SESSION['write_error'] = '파일 업로드 success!';
} else {
$_SESSION['write_error'] = '파일 업로드 Fail ㅜㅜ';
}
} else {
};
//쿼리문 실행
$query = "UPDATE qna_board SET name='$username',phone='$bPhone',title='$bTitle',content='$bContent',lock_post='$lock_post',file='$new_filename' WHERE number='$bno'";
$result = $con->query($query);
echo "수정이 완료되었습니다!<br><br>";
echo "<a href='qna_board.php'><button>게시판으로 돌아가기</button></a>";
?>
qna_write_proc.php와 비슷하지만
UPDATE~ SET 쿼리문을 사용한다
$query = "UPDATE qna_board SET name='$username',phone='$bPhone',title='$bTitle',content='$bContent',lock_post='$lock_post',file='$new_filename' WHERE number='$bno'";
$result = $con->query($query);
밑은 qna_board.php의 일부코드이다.
SQL쿼리문으로 게시글의 lock_post값을 보고 1이면 잠금 표시, 0이면 열어준다
그리고 문의게시글db내에 이름 조회가 안되면 익명으로 설정한다.
qna_board.php 일부
$title = $board['title']; //게시글 제목
$number = $board['number']; //게시글 번호
$lockpost = $board['lock_post'];
if(isset($board['name'])){
$name = $board['name']; //작성자
} else {
$name = "익명";
}
<?php
$locking = "<img src='./lockpost.png' alt='lock' title='lock' width='20' height='20'";
if($lockpost == '0'){ ?>
<a href="./qna_read.php?number=<?php echo $board['number'];?>"><?php echo $title;?></td>
<?php } else { ?>
<a href="./ck_read.php?number=<?php echo $board['number'];?>"><?php echo $title,$locking;?></td>
<?php }
?>
$lockpost가 0이라면 qna_read.php로 바로 연결해주는 링크를 걸어주고
$lockpost가 1이라면 ck_read.php로 연결지어서 전화번호 인증을 거치는 창으로 연결지어주고
제목 옆에 잠금표시 이미지를 같이 띄워준다.
잠금 표시가 된 게시글을 클릭하면 ck_read.php페이지로 넘어가고
전화번호를 입력하는 창을 받게 된다.
ck_read.php의 코드입니다
ck_read.php
<?php
session_start();
$con = mysqli_connect('localhost','root','1234','test');
$id = $_GET['number'];
$query = "SELECT * FROM qna_board WHERE number='$id'";
$result = $con->query($query);
$q_board = $result -> fetch_array();
?>
<form method="POST" action="qna_read.php?number=<?php echo $id?>">
전화번호를 입력하세요<input type="password" name=phone>
<input type="submit" value="확인">
</form>
DB와 연결 후 form 태그를 통해 전화번호를 인증하는데 이 값은 qna_read.php로 전달되어
조건문을 통과하면 게시글을 보여주고 인증에 실패하면 문의 게시판 메인으로 되돌아간다.
인증에 성공하면 alert창을 보여주고 확인을 누르면 게시글을 보여준다.
게시글이 잘 보인다
만약 인증에 실패하면 문의 게시판 메인으로 되돌아가고 하단에 세션 메시지로 전화번호 인증에 실패했다는 문구가 뜬다.
아래는 qna_read.php의 코드 전문이다
qna_read.php
<?php
//세션 시작
session_start();
if(isset($_SESSION['id'])){
$login_id = $_SESSION['id'];
} else {
$login_id = "익명";
}
//클릭할 때 number GET으로 가져옴
$bno = $_GET['number'];
//전화번호 인증한거 변수로 저장
$pw_phone = $_POST['phone'];
//게시판 DB 연결
$con = mysqli_connect('localhost','root','1234','test');
//SQL Injection 대응
$boardlike_id = mysqli_real_escape_string($con,filter_var(strip_tags($bno), FILTER_SANITIZE_SPECIAL_CHARS));
//게시판 내용 보여주기
$query = "SELECT * FROM qna_board WHERE number='".$bno."'";
$result = $con->query($query);
$board = $result->fetch_array();
//문의게시판에는 조회수 기능 필요 없음
// $hit = $board['hit'];
// $hit = $hit + 1;
// $hit_query = "UPDATE board SET hit = '".$hit."' WHERE number ='".$bno."'";
// $hit_result = $con->query($hit_query);
if($board['lock_post']=='1'){
if($board['phone']==$pw_phone){
echo "<script>alert('전화번호 인증에 성공했습니다!')</script>";
} else {
$_SESSION['msg'] = "전화번호 인증에 실패했습니다";
header("Location: ./qna_board.php");
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>문의 게시판</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<?php
require('./nav.html');
?>
<!-- 게시글 불러오기 -->
<h2><?php echo $board['title']; ?></h2><HR>
<div>작성자 :<?php echo $board['name']; ?>
<?php echo " 작성날짜 : ".$board['date']; ?></div>
<!-- 기준선 -->
<HR>
<?php
$filename = explode('_', $board['file'])[1]; //타임스탬프를 제거 후 파일명만 분리
$download_url = 'download_proc.php?filename='.$board['file'];
echo '<p>파일 : <a href="'.$download_url.'">'.$filename.'</a></p>';
?>
<textarea style="width:100%; height:15rem;" readonly><?php echo $board['content']; ?></textarea>
<br><Br>
<a href="./qna_modify.php?number=<?php echo $board['number'];?>"><button class="btn btn-secondary">수정</button></a>
<a href="./qna_delete.php?number=<?php echo $board['number'];?>" onclick="return confirm('정말로 삭제하시겠습니까? 삭제 후에는 되돌릴 수 없습니다.')"><button class="btn btn-secondary">삭제</button></a>
<a href="./qna_board.php"><button class="btn btn-secondary">목록</button></a>
<p>
<?php
if(isset($_SESSION['write_error'])){
echo $_SESSION['write_error'];
unset($_SESSION['write_error']);
}
?>
</body>
</html>
비밀글 설정을 하지 않고 작성을 해보자
글쓰기 완료가 되었다는 문구가 뜨고 목록으로 돌아가면
잠금 표시도 안 뜨고
클릭하면 바로 게시글을 보여준다
로그인을 해서 세션아이디가 있다면 그 아이디로 글 작성이 된다
아직 미숙하지만 장장 3개월간 꾸준히 만든 결과물이고
뼈다귀같던 기존의 내 웹화면이 부트스트랩도 넣고 나름 커스텀한 css도 넣으면서 조금씩
바뀐 게 신기하기만 하다
몇달전 포스팅한 것과 지금 웹 화면을 비교해보면 감개무량하다
끝까지 마무리할 수 있어서 너무 뿌듯하다
이제 이 기반을 바탕으로 멋진 해커가 되자!
'개발 > 웹 개발' 카테고리의 다른 글
Swagger로 문서 API 자동화 (0) | 2023.08.10 |
---|---|
[14주차] 문의 게시판 구현 #1 - 문의 글 작성 (1) | 2023.06.25 |
[14주차] 마이 페이지 구현 #3 - 비밀번호 변경 기능 (0) | 2023.06.24 |
[13주차] 마이 페이지 구현 #2 - 개인 정보 수정 기능 구현 (0) | 2023.06.22 |
[13주차] 마이 페이지 구현 #1 - 자신의 정보 확인 (0) | 2023.06.20 |