Laravelでブログサイトを作る 17. フロントページ

はじめに
今回の、フロント側作成によって、ブログは一応の完成となります。
カテゴリを管理し、記事を作成編集でき、それを表示する。ごくごくシンプルな構成ですが、ブログとしての最低限が備わった状態になります。
そしてその作業ですが、実はほとんどありません。
Controller
app/Http/Controllers/ArticleController.php
一覧
ルーティングの際に設定した、一覧表示画面を用意します。
新着順、親子カテゴリの絞り込み、検索。前々回、前回で、管理画面で用意したものとほとんど同じです。
違う点は、以下の2つ。
- 削除済み記事を出さない→
getList()の第2引数をfalseにしてあげればOKです - フロント用のテンプレートを使う→
listView()の第2引数をfrontに変更
/**
* 記事一覧
*
* @return mixed
*/
public function list() {
// ブログ記事一覧を取得
$articleData = $this->article->getList($this->ADMIN_LIST_NUM, false);
return $this->listView($articleData, 'front');
}
/**
* 親カテゴリ別記事一覧
*
* @param string $parent
* @return mixed
*/
public function parentList(string $parent) {
// ブログ記事一覧を取得
$articleData = $this->article->getList($this->ADMIN_LIST_NUM, false, (int)$parent);
return $this->listView($articleData, 'front');
}
/**
* 子カテゴリ別記事一覧
*
* @param string $child
* @return mixed
*/
public function childList(string $child) {
// ブログ記事一覧を取得
$articleData = $this->article->getList($this->ADMIN_LIST_NUM, false, 0, $child);
return $this->listView($articleData, 'front');
}
/**
* 記事一覧(ワード検索)
*
* @param Request $request
* @return mixed
*/
public function searchList(Request $request) {
// ブログ記事一覧を取得
$articleData = $this->article->getList($this->ADMIN_LIST_NUM, false, 0, 0, $request['search']);
return $this->listView($articleData, 'front');
}
記事詳細
① 記事取得
記事テーブルと親カテゴリテーブルのJoinは、カテゴリ名を取得するための連結です。後述の子カテゴリ同様に、記事の終わりにカテゴリ別一覧へのリンク生成に使います。
一覧のようにget()を使うのではなく、first()を使っているのは、主キーで検索しているからです。
② 記事と関連付けられている子カテゴリの情報を取得
記事のIDが固定なので、そこに関連する子カテゴリを取得します。関連付けテーブルと子カテゴリテーブルをJoinして、カテゴリ名も取得します。
/**
* 記事詳細
*
* @param string $id
* @return mixed
*/
public function content(string $id) {
// ① 記事取得
$articleData = $this->article
// 親カテゴリについても取得
->leftJoin(
'parent_categories',
function ($join) {
$join->on('articles.parent', '=', 'parent_categories.id');
}
)
// ID指定して1件分のデータを取得
->where('articles.id', $id)->first();
if ($articleData === null) {
// 記事データが見つからない場合はエラー出力する
return $this->error('warning', '記事が見つかりません。');
}
// ② 記事と関連付けられている子カテゴリの情報を取得
$articleChildrenData = $this->articleChild
->leftJoin('child_categories', function ($join) {
$join->on('article_children.children', '=', 'child_categories.id');
})->where('article_children.article', $id)->get();
// 親カテゴリを取得
$parentCategoryList = $this->parentCategory->orderBy('number', 'asc')->orderBy('id', 'asc')->get();
// 子カテゴリは、キーを親カテゴリIDにした連想配列にする
$data = $this->childCategory->orderBy('number', 'asc')->orderBy('id', 'asc')->get();
$childCategoryList = [];
foreach ($data as $item) {
$childCategoryList[$item->parent][] = $item;
}
return view('front.article', [
'articleData' => $articleData,
'articleChildrenData' => $articleChildrenData,
'parentCategoryList' => $parentCategoryList,
'childCategoryList' => $childCategoryList,
]);
}
/**
* エラー出力
*
* @param string $type
* @param string $message
* @return mixed
*/
public function error(string $type, string $message) {
// $typeに特定文字列以外を指定させない
if (!in_array($type, ['information', 'caution', 'warning'])) {
$type = 'information';
}
return view('front.error', [
'type' => $type,
'message' => $message,
]);
}
テンプレート
記事詳細
resources/views/front/article.blade.php
あまり、特筆することはありません。記事のタイトルと本文を表示し、属するカテゴリの表示と、それぞれの絞り込み一覧へのリンクを生成しています。
@extends('front.app')
@section('title')
{{ $articleData->title }}
@endsection
@section('main')
<article>
<section class="article">
{{-- 記事タイトル --}}
<h2>{{ $articleData->title }}</h2>
{{-- 本文 --}}
{!! $articleData->body !!}
{{-- 親子カテゴリ --}}
<div class="articleCategory">
<ul>
<li>
<a href="{{ route('list_parent', ['id' => $articleData->parent]) }}">
{{ $articleData->name }}
</a>
</li>
@foreach ($articleChildrenData as $articleChildren)
<li>
<a href="{{ route('list_child', ['id' => $articleChildren->children]) }}">
{{ $articleChildren->name }}
</a>
</li>
@endforeach
</ul>
</div>
{{-- 公開日時 --}}
<p class="articleDate">{{ $articleData->created_at }}</p>
</section>
</article>
@endsection
エラー
resources/views/front/error.blade.php$typeはエラーレベルを指定するイメージです。ひとまず「通知(information)」「注意(caution)」「警告(warning)」を想定しています。
@section('title', 'エラー')
@section('main')
<article>
<section class="article">
<div class="{{ $type }}"><p>{{ $message }}</p></div>
</section>
</article>
@endsection
2022-05-20 09:00:00
