이번 챕터의 코드는 https://github.com/koeunyeon/ci4/commits/refacto-post-list 에 있습니다.
이제 글 목록 서비스의 마지막 메소드이므로, 글 모델의 반환 타입을 변경해도 다른 사이드 이펙트가 생기지 않는다고 판단할 수 있습니다. 따라서 모델의 반환 타입을 변경합니다.
app/Models/PostsModel.php
protected $returnType = "App\Entities\PostEntity";
서비스의 조회 메소드 find()
에서 asObject
메소드를 통해 캐스팅했었죠. 이렇게요.
app/Services/PostService.php
return $postModel->asObject("App\Entities\PostEntity")->find($post_id);
이제 모델이 직접 엔티티를 반환함으로 캐스팅할 필요가 없어졌으므로 아래처럼 바꾸겠습니다.
return $postModel->find($post_id);
이제 글 목록을 반환하는 서비스를 만들어 보겠습니다. PostService
에 아래 메소드를 추가합니다.
public function post_list($page)
{
$model = new PostsModel();
$post_query = $model->orderBy("created_at", "desc");
$post_list = $model->paginate(10, "default", $page); // (1)
$pager = $post_query->pager;
return [$pager, $post_list];
}
(1) 기존 Post
컨트롤러의 index()
엔드포인트에서 페이징을 하는 코드는 아래와 같았습니다.
$model->paginate(10);
이는 paginate
메소드의 두번째 파라미터부터는 기본 인수가 지정되어 있었기 때문인데요. 세번째 파라미터 $page
는 입력되지 않을 경우 쿼리 스트링 page
값을 읽어서 처리하는 방식으로 동작합니다. 물론 PHP의 특성상 쿼리 스트링을 읽는 슈퍼 글로벌 변수 $_GET
은 어디서든 접근할 수 있지만, 서비스 레이어는 HTTP 레이어에 가능한 관여하지 않는 것이 원칙이므로 post_list
메소드의 파라미터로 입력받도록 처리합니다.
컨트롤러 메소드 index()
를 아래와 같이 변경합니다.
public function index()
{
$page = $this->request->getGet("page") ?? 1; // (1)
list($pager, $post_list) = PostService::factory()->post_list($page);
return view("post/index", [
'post_list' => $post_list,
'pager' => $pager,
'isLogin' => LoginHelper::isLogin()
]);
}
(1) 코드이그나이터4 컨트롤러에서 쿼리 스트링을 읽는 방법은 $this->request->getGet
입니다. 뭔가 이상한 것 같기도 하고 나름 일리는 있는것도 같은 메소드명이네요. 서비스에 현재 페이지를 전달하기 위해 사용합니다.
이제 마지막으로 해야 할 것은 뷰를 수정하는 겁니다. 배열 대신 엔티티를 사용할 수 있도록 수정합시다.
app/Views/post/index.php
<?= $this->extend('/post/layout') ?>
<?= $this->section('content') ?>
<?php
function show_content($content)
{
$content = strip_tags($content); // (1)
if (mb_strlen($content) > 100) { // (2)
$content = mb_substr($content, 0, 100); // (3)
}
return $content;
}
foreach ($post_list as $post) {
?>
<div class="item mb-5">
<div class="media">
<div class="media-body">
<h3 class="title mb-1">
<a href="<?= site_url("/post/show/{$post->post_id}") ?>"><?= $post->title ?></a>
</h3>
<div class="meta mb-1">
<span class="date"><?= $post->created_at ?></span>
<div class="intro"><?= show_content($post->html_content) ?></div>
<a class="more-link" href="<?= site_url("/post/show/{$post->post_id}/#content") ?>">Read more →</a>
</div>
</div>
</div>
<?php
}
?>
<?php $pager->setPath("/post"); ?>
<?= $pager->links() ?>
<?php if ($isLogin) : ?>
<p style="text-align: right;">
<a href="/post/create" class="btn btn-primary">글쓰기</a>
</p>
<?php endif ?>
<?= $this->endSection() ?>