Ikeda's Blog

Laravelでブログサイトを作る 10. テンプレートの作成

はじめに

今回は、サイトのデザインを作成します。
プログラム作ってからだと、「あれ足りない」「これ足りない」という事態が起きやすいので、先に、各URLへアクセスした際に、ただページを表示させるだけのものを作ります。

LaravelはBladeというテンプレートを採用しており、これを使用して構築していきます。
Bladeに限りませんが、継承機能がありますので、これを利用して構築していきます。

おおまかな構成は、以下のようにします。

+ resources/views
  + app.blade.php -> 全体の共通部分
  + front
  | + app.blade.php -> 公開ページの共通部分
  | + article.blade.php -> 記事1件のページ
  | + list.blade.php -> 記事一覧のページ(親子カテゴリ絞り込み等でも同じテンプレートを使う)
  + admin
    + app.blade.php -> 管理ページの共通部分
    + articleEdit.blade.php -> 記事の編集ページ
    + articleList.blade.php -> 記事の一覧ページ
    + parent.blade.php -> 親カテゴリの一覧・編集ページ
    + child.blade.php -> 子カテゴリの一覧・編集ページ

Controller

TOPページのルーティングは、以下のようになっている。

Route::group(['prefix' => '/', 'namespace' => 'App\\Http\\Controllers\\'], function() {
    Route::get('/', 'ArticleController@list')->name('top');
});

なので、TOPページにアクセスした時には、app/Http/Controllers/ArticleController.phpのlistメソッドが実行されます。
ArticleController.phpの内容を、以下のようにします。テンプレートを読み込んで表示するだけです。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ArticleController extends Controller
{
    /**
     * 一覧画面表示
     */
    public function list()
    {
        // view()で引数としている文字列は、resources/views以下のテンプレートファイルを表しています。
        // 「.」(ドット)でディレクトリが表現されるので、上記の場合は、
        // `resources/views/front/articleList.blade.php`
        // を表示します。
        return view('front.articleList');
    }
}

テンプレート・全体の共通部分

サイト全体の共通部分を作成します。
対象は、resources/views/app.blade.phpです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    {{--
    ***@yield*** は、子孫テンプレートで設定した値が入ります。
    例えば、タイトルタグ内に`@yield('title')`と記述することで、
    子孫テンプレートでそれぞれに設定して出し分けることが可能となります。
    --}}
    <title>サイトタイトル | @yield('title')</title>

    {{--
    ***asset()*** は、https(またはhttp)からはじまる、public以下のURLを生成してくれます。
    この方法で記述を統一することで、「画像やJS、CSSファイルをAWS S3に置く」などの
    変更が起きた際、`env`を書き換えるだけで済むので、大変便利です。
    --}}
    <link rel="stylesheet" href="{{ asset('/css/style.css') }}">

    <script type="text/javascript" src="{{ asset('/js/jquery.min.js') }}" charset="UTF-8"></script>
    <script type="text/javascript" src="{{ asset('/js/main.js') }}" charset="UTF-8"></script>
    <script src="https://kit.fontawesome.com/207c617789.js" crossorigin="anonymous"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>

<body>

<header>
    <h1><a href="/"><img src="{{ asset('/img/header.png') }}" alt="サイトタイトル" /></a></h1>
</header>

<main>
    @yield('paging')

    @yield('main')

    <aside>
        @yield('aside')
    </aside>

    @yield('paging')
</main>

<footer>
    フッターテキスト
</footer>

</body>
</html>

テンプレート・公開ページの共通部分

先程のサイト全体(親)に対し、公開ページの共通部分(子)を作成します。
ファイルは、resources/views/front/app.blade.phpです。

{{--
***@extends*** は、継承元となるテンプレートを指定します。
ここでは、全体の共通部分`resources/views/app.blade.php`が対象です。
--}}
@extends('app')

{{--
***@section*** は、上位テンプレートで`@yield`を使用した箇所に挿入する内容を記述します。
@sectionから@endsectionまでの内容が対象となります。
以下の例では、`@yield('aside')`に出力されるサイドメニューの内容を記述しています。
--}}
@section('aside')
    <section class="side">
        <h3>検索</h3>
        <div id="searchWrapper">
            <form action="{{ route('list_search') }}" method="post" name="searchForm">
                {{ csrf_field() }}
                <input type="text" id="searchTxt" name="search" placeholder="サイト内検索" />
                <a href="#" id="searchBtn"><i class="fas fa-search"></i></a>
            </form>
        </div>
    </section>
@endsection

テンプレート・個別ページ

最後に、個別ページ(孫)を作成します。
ファイルは、resources/views/front/articleList.blade.phpです。

{{--
継承元のテンプレートファイルを指定します。
ルールは、Controller同様に「.」(ドット)でディレクトリの区切りです。
以下の場合は、`resources/views/front/app.blade.php`を表しています。
--}}
@extends('front.app')

{{--
@sectionは、一行で記述することも可能です。
以下のように、
--}}
@section('title', '記事一覧')

@section('paging')
    <nav>
        <ul class="pagination">
            <li><a href="/" rel="prev" aria-label="« Previous">&lt;&lt;</a></li>
            <li><a href="/">1</a></li>
            <li><a href="/">2</a></li>
            <li><a href="/">3</a></li>
            <li class="active" aria-current="page"><span>4</span></li>
            <li class="disabled" aria-disabled="true" aria-label="Next »">
                <span aria-hidden="true">&gt;&gt;</span>
            </li>
        </ul>
    </nav>
@endsection

@section('main')
    <article>
        <section class="article">
            <h2><a href="#">記事タイトル</a></h2>

            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>

            <a href="#" class="more">続きを読む</a>
        </section>
        <section class="article">
            <h2><a href="#">記事タイトル</a></h2>

            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>

            <a href="#" class="more">続きを読む</a>
        </section>
        <section class="article">
            <h2><a href="#">記事タイトル</a></h2>

            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>

            <a href="#" class="more">続きを読む</a>
        </section>
        <section class="article">
            <h2><a href="#">記事タイトル</a></h2>

            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>

            <a href="#" class="more">続きを読む</a>
        </section>
        <section class="article">
            <h2><a href="#">記事タイトル</a></h2>

            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>
            <p>これはテストです。</p>

            <a href="#" class="more">続きを読む</a>
        </section>
    </article>
@endsection

以上で、テンプレートの表示は完了です。
あとは、public/css/style.cssを編集してデザインを整えておきましょう。
http://192.168.56.10/で確認できます。

テンプレート・管理画面の共通部分

なお、管理画面の共通テンプレートは以下のようにしました。
違いとしては、管理画面用のCSSとJavaScriptを読み込むようにしています。
あとは、サイドメニューに各管理機能のリンクを設置しております。

@extends('app')

@section('title')
    @yield('adminTitle')
@endsection

@section('main')
    {{-- 管理画面専用のCSSとJavaScript --}}
    <link rel="stylesheet" href="{{ asset('/css/admin.css?v=').'?'.time() }}">
    <script type="text/javascript" src="{{ asset('/js/admin.js?v=').'?'.time() }}" charset="UTF-8"></script>
    @yield('adminMain')
@endsection

@section('aside')
    <section class="aside">
        <h3>メニュー</h3>
        <ul>
            <li><a href="{{ route('admin_parent') }}">親カテゴリ管理</a></li>
            <li><a href="{{ route('admin_child') }}">子カテゴリ管理</a></li>
            <li><a href="{{ route('admin_article_list') }}">記事一覧</a></li>
            <li><a href="{{ route('admin_article_edit') }}">記事新規作成</a></li>
        </ul>
    </section>
@endsection