이전글 : [PHP] 게시판 만들기 with MVC - 1부 Migration
이전글 : [PHP] 게시판 만들기 with MVC - 2부 Routing
이전글 : [PHP] 게시판 만들기 with MVC - 3부 View(List & Create)
이전글 : [PHP] 게시판 만들기 with MVC - 4부 Controller
이전글 : [PHP] 게시판 만들기 with MVC - 5부 Pagination
잡담
생각보다 포스팅이 많아질 것 같습니다.
만약에 이 포스팅을 보고 공부 중이시라면 언제든지 궁금한 점을 댓글로 달아주세요.
제가 어떻게 하고 있는지에 피드백이 있으면 좋습니다.
View
저번까지 Post List을 만들었으니 이번에는 Post 상세 페이지, Read 기능을 만들어봅시다.
해당 게시판은 로그인 기능이 없는 익명 게시판이므로 잠긴 글여부나 추천 여부, 조회수 여부에 대한 중복 방지는
쿠키를 사용해서 해결합니다.
View를 만들어줍시다
bbs/view/read.php
<!doctype html>
<?php
use Model\Post;
include "part/header.php";
?>
<body>
<div class="m-4">
<div class="container mt-5">
<h3 class="d-inline"><a href="/bbs">자유게시판</a></h3>/<h4 class="d-inline">글 읽기</h4>
<p class="mt-1 mb-3">글의 상세 내용입니다.</p>
<hr/>
<?php
$idx = $_GET['idx'];
$post = new Post();
$postInfo = $post->getPost($idx);
if ($postInfo) {
// 게시글의 락 여부와 락 쿠키 체크
$pass = false;
if (isset($_COOKIE['post_key' . $postInfo['idx']])
&& password_verify($_COOKIE['post_key' . $postInfo['idx']], $postInfo['pw'])) {
$pass = true;
}
if ($postInfo['lock'] == 1 && !$pass) {
?>
<form action="/bbs/post/lockCheck" method="post">
<p>비밀글입니다, 보기 위해서는 비밀번호가 필요합니다.</p>
<div class="form-group">
<input type="hidden" name="idx" value="<?= $idx ?>">
<label for="pw">Password</label>
<input id="pw" type="text" class="form-control" name="pw" placeholder="비밀번호를 입력하세요">
</div>
<button type="submit" class="btn btn-primary">확인하기</button>
<a href="/bbs" class="btn btn-secondary">목록</a>
</form>
<?php
} else {
$viewsBonus = 0;
if (!isset($_COOKIE['post_views' . $idx])) {
$post->increaseViews($idx);
$viewsBonus = 1;
}
?>
<div>
<h5 class="d-inline">제목) <?= $postInfo['title'] ?></h5>
<p class="float-right">글쓴이) <?= $postInfo['name'] ?></p>
</div>
<span class="mr-2">작성일: <?= $postInfo['created_at'] ?></span>
<span class="mr-2">수정일: <?= $postInfo['updated_at'] ?></span>
<span class="mr-2">조회수: <?= $postInfo['views'] + $viewsBonus ?></span>
<span class="mr-2">추천수: <?= $postInfo['thumbs_up'] ?></span>
<hr/>
<div class="card mb-3">
<div class="card-body">
<p class="card-text">
<?= nl2br($postInfo['content']) ?>
</p>
</div>
</div>
<a href="./update?idx=<?= $postInfo['idx'] ?>" class="btn btn-primary">수정하기</a>
<a href="/bbs" class="btn btn-secondary">목록</a>
<a href="./delete?idx=<?= $postInfo['idx'] ?>" class="btn btn-dark">삭제하기</a>
<button class="btn btn-success" id="thumbsUp">
추천 <?= $postInfo['thumbs_up'] != 0 ? "(" . $postInfo['thumbs_up'] . ")" : '' ?>
<span class="material-symbols-outlined" style="font-size:16px">thumb_up</span>
</button>
<!--추천에서 사용할 postIdx 값-->
<input type="hidden" id="postIdx" value="<?= $idx ?>">
<?php
}
} else {
echo "<script>alert('존재하지 않는 게시물입니다.');history.back();</script>";
}
?>
</div>
<script src="/bbs/assets/script/read.js"></script>
</body>
</html>
이번에는 추천 기능을 위한 read.js가 포함됩니다.
bbs/assets/script/read.js
$(document).ready(function () {
// 추천 기능
$("#thumbsUp").click(function () {
$.ajax({
url: "/bbs/post/thumbsUp",
type: "POST",
data: {
post_idx: $("#postIdx").val()
},
success: function (data) {
alert(data.msg);
if (data.result) {
location.reload();
}
},
error: function (e) {
alert("에러 발생");
}
});
});
});
Route
Read 페이지의 접근과 추천 기능의 Ajax 요청을 받을 라우트 설정을 합시다.
bbs/Route/PostRoute.php
<?php
namespace Route;
use Controller\PostController;
class PostRoute extends BaseRoute
{
function routing($url): bool
{
$PostController = new PostController();
if ($this->routeCheck($url, "post/list", "GET")) {
return $this->requireView('index');
} else if ($this->routeCheck($url, "post/read", "GET")) {
return $this->requireView('read');
} else if ($this->routeCheck($url, "post/create", "GET")) {
return $this->requireView('create');
} else if ($this->routeCheck($url, "post/create", "POST")) {
$PostController->create();
return true;
} else if ($this->routeCheck($url, "post/thumbsUp", "POST")) {
$PostController->thumbsUp();
return true;
} else {
return false;
}
}
}
Controller
이제 컨트롤러에 thumbsUp을 추가합시다
Read 페이지는 바로 View에 접속하니 Controller가 필요 없습니다.
<?php
namespace Controller;
use Model\Post;
class PostController extends BaseController
{
...
/**
* 추천 기능을 담당
* @return void
*/
public function thumbsUp()
{
$postIdx = $_POST['post_idx'];
if ($this->parametersCheck($postIdx)) {
$this->echoJson($this->post->thumbsUp($postIdx));
} else {
$this->redirectBack('입력되지 않은 값이 있습니다.');
}
}
}
Model
이제 Post Model에서 Post 데이터를 가져오기 위한 getPost와 조회수 증가를 위한 increaseViews, 추천 기능을 위한 thumbsUp을 추가합니다.
<?php
namespace Model;
use PDO;
use PDOException;
class Post extends BaseModel
{
...
/**
* Post 데이터 가져오기
* @param $idx int Post의 idx
* @return array|mixed
*/
public function getPost(int $idx)
{
try {
$query = "SELECT * FROM posts WHERE idx = :idx LIMIT 1";
$stmt = $this->conn->prepare($query);
$stmt->execute([
'idx' => $idx
]);
return $stmt->fetch();
} catch (PDOException $e) {
error_log($e->getMessage());
return false;
}
}
/**
* Post 조회 수 증가
* @param $idx int Post의 idx
* @return bool|void
*/
public function increaseViews($idx)
{
try {
// post_views 쿠키가 없으면 조회수 증가
if (!isset($_COOKIE['post_views' . $idx])) {
$stmt = $this->conn->prepare("update posts set views = views + 1 where idx = :idx");
$stmt->bindParam('idx', $idx);
$stmt->execute();
// 조회수 증가 후 하루짜리 쿠키 생성
setcookie('post_views' . $idx, true, time() + 60 * 60 * 24, '/');
return true;
}
} catch (PDOException $e) {
error_log($e->getMessage());
return false;
}
}
/**
* Post 추천 기능
* @param $idx int Post의 idx
* @return array
*/
public function thumbsUp(int $idx): array
{
try {
// 쿠키 체크
if (isset($_COOKIE["post_thumbs_up" . $idx])) {
return [
'result' => false,
'msg' => '이미 추천하셨습니다.'
];
}
// 추천 수 증가
$query = "UPDATE posts SET thumbs_up = thumbs_up + 1 WHERE idx = :idx";
$result = $this->conn->prepare($query)->execute([
'idx' => $idx
]);
// 결과 값 리턴 + 쿠키 생성
if ($result) {
setcookie("post_thumbs_up" . $idx, true, time() + 60 * 60 * 24, "/");
return [
'result' => true,
'msg' => '추천되었습니다.'
];
}
return [
'result' => false,
'msg' => '추천에 실패했습니다.'
];
} catch (PDOException $e) {
error_log($e->getMessage());
return [
'result' => false,
'msg' => '알 수 없는 에러가 발생했습니다, 관리자에게 문의주세요.'
];
}
}
}
이제 Read 페이지의 기능을 구현했습니다
아래와 같은 결과를 볼 수 있을 겁니다.
'PHP > Modern PHP' 카테고리의 다른 글
[PHP] 게시판 만들기 with MVC - 8부 Lock (0) | 2023.12.28 |
---|---|
[PHP] 게시판 만들기 with MVC - 7부 Update & Delete (0) | 2023.12.27 |
[PHP] 게시판 만들기 with MVC - 5부 Pagination (1) | 2023.12.27 |
[PHP] 게시판 만들기 with MVC - 4부 Controller (0) | 2023.12.27 |
[PHP] 게시판 만들기 with MVC - 3부 View(List & Create) (1) | 2023.12.27 |