Ikeda's Blog

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