build();
});
return response($xml, 200)->header('Content-Type', 'application/xml; charset=utf-8');
}
private function build(): string
{
// 레이아웃의 canonical(url()->current())과 같은 방식으로 요청 기준 주소를 쓴다.
// config('app.url') 은 환경파일 값에 좌우되어(로컬은 local-blog.web.or.kr) 어긋날 수 있다.
$baseUrl = rtrim(url('/'), '/');
$today = date('Y-m-d');
$xml = '' . PHP_EOL;
$xml .= '' . PHP_EOL;
// 고정 페이지
$xml .= $this->url("{$baseUrl}/", $today, 'daily', '1.0');
$xml .= $this->url("{$baseUrl}/recently", $today, 'daily', '0.8');
$xml .= $this->url("{$baseUrl}/tag", $today, 'daily', '0.6');
// 문서 페이지. tb_document 에 노출 여부 컬럼을 확인하지 못해 현재 공개된 두 건만 둔다.
$xml .= $this->url("{$baseUrl}/document/profile", $today, 'monthly', '0.5');
$xml .= $this->url("{$baseUrl}/document/proposal", $today, 'monthly', '0.5');
// 게시판 목록
$boards = DB::table('tb_board')
->where('is_display', '=', 1)
->orderBy('sort')
->pluck('code');
foreach ($boards as $code) {
$xml .= $this->url("{$baseUrl}/board/{$code}", $today, 'daily', '0.8');
}
// 게시글. 공지/전체공지도 실제로 열리는 페이지이므로 함께 넣는다.
DB::table('tb_post')
->join('tb_board', 'tb_board.id', '=', 'tb_post.board_id')
->where('tb_board.is_display', '=', 1)
->where('tb_post.is_delete', '=', 0)
->where('tb_post.is_secret', '=', 0)
->where('tb_post.is_personal', '=', 0)
->select('tb_board.code', 'tb_post.id', 'tb_post.updated_at', 'tb_post.created_at')
->orderBy('tb_post.id')
->chunk(1000, function ($posts) use (&$xml, $baseUrl, $today) {
foreach ($posts as $post) {
$modified = $post->updated_at ?: $post->created_at;
$lastModified = $modified ? date('Y-m-d', strtotime($modified)) : $today;
$xml .= $this->url("{$baseUrl}/board/{$post->code}/{$post->id}", $lastModified, 'weekly', '0.6');
}
});
$xml .= '' . PHP_EOL;
return $xml;
}
private function url(string $location, string $lastModified, string $changeFrequency, string $priority): string
{
return ' ' . PHP_EOL
. ' ' . htmlspecialchars($location, ENT_XML1) . '' . PHP_EOL
. ' ' . $lastModified . '' . PHP_EOL
. ' ' . $changeFrequency . '' . PHP_EOL
. ' ' . $priority . '' . PHP_EOL
. ' ' . PHP_EOL;
}
}