Laravel 10 入門トップページ


目次

  1. プロジェクトを作成する
  2. データベースファイルを作成する
  3. Visual Studio Code を設定する
  4. .env を編集して初期設定する
  5. タイムゾーンと言語を設定する
  6. Webサーバを起動して終了する
  7. マイグレーションファイルを生成する
  8. テスト用データを設定する
  9. モデルを作成する
  10. コントローラを作成する
  11. ルートを定義する
  12. データベースからデータを取り出す
  13. トップページにリンクを設置する
  14. ビューを使ってレコードを表示する
  15. コメントを個別に表示するページを作成する
  16. コメント投稿機能を実装する
  17. 投稿内容を検証する
  18. 投稿内容を編集する
  19. 投稿コメントを削除する
  20. テストの自動化を実現する
  21. テストカバレッジを計測する
  22. 複数のLinuxコマンドを実行し,履歴からも実行する
  23. ビューをレイアウト化する
  24. Bootstrap を導入する
  25. SQLite を操作する
  26. フェイカでシーダを拡張する
  27. ページネーションを作る
  28. シーダに登録日時と更新日時を追加する
  29. 一覧表示を更新日時の降順にする
  30. フラッシュメッセージを表示する
  31. スタイルシートでデザインを整える

Laravel によるコメント掲示板の開発

ビューをレイアウト化する

ここまでの作業でコメントの一覧表示や個別表示,投稿,編集などの基本的な機能が完成しました.各機能のビュー(index.blade.php や show.blade.php)の内容はその多くが共通しています.特にページのデザインなどに関する部分をレイアウト化(テンプレート化)しておくと,システム全体でビューのデザインを変更したいときに1つのファイルを編集するだけでできるようになります.これからの作業は小さなシステムの開発時には必要性は感じられないかもしれません.若干面倒な作業になるかもしれませんが,規模の大きなシステムを開発するときには開発の初期段階でレイアウト化を行なっておくと後々にその有り難みを感じられることでしょう.

まず,resouces/view/layouts ディレクトリを作成します.これまでに作成した index.blade.php や show.blade.php などのファイル群で共通する部分を定義したレイアウトファイル default.blade.php を作成したディレクトリに設置します.通常のHTMLファイルの雛形と異なる部分は5行目と9行目の @ で始まる部分だけです.この default.blade.php が共通のレイアウトを定義した親のビューという位置付けになります.

resources/views/layouts/default.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>@yield('title')</title>
</head>
<body>
    <div class="container">
        @yield('content')
    </div>
</body>

続いて今作成した共通レイアウトの親ビューを使用するように resources/views/comments/index.blade.php を修正します.1行目の @extends('layouts.default') によって,layouts ディレクトリに設置された default.blade.php がレイアウトとして使用されます.3行目の @section('title', 'コメントの一覧') によって,title セクションが定義され,title セクションの内容 コメントの一覧 が共通レイアウトの @yield('title') の部分に埋め込まれます.また,5行目から41行目が content セクションとして定義されたので,共通レイアウトの9行目にある @yield('content') の部分に埋め込まれることになります.なお,content セクションの内容は以前の index.blade.php<body> 〜 </body> 内部のコードをそのままコピーするだけで構いません.

resources/views/comments/index.blade.php@extends('layouts.default')

@section('title', 'コメントの一覧')

@section('content')
<h1>コメント一覧</h1>
<ul>
    @foreach ($comments as $comment)
        <li>
            <a href="{{ route('comments.show', ['comment_id' => $comment->id]) }}">
                {{ $comment->title }}
            </a>
        </li>
    @endforeach
</ul>

<h1>コメント投稿</h1>
<div>
    <form method="post" action="{{ route('comments.store') }}">
        @csrf
        <p>
            <label for="title">Title: </label>
            <input type="text" name="title" id="title" value="{{ old('title') }}">
            @if ($errors->has('title'))
                <span class="error">{{ $errors->first('title') }}</span>
            @endif
        </p>

        <p>
            <label for="body">Body: </label>
            <textarea name="body" id="body" rows="4" cols="50">{{ old('body') }}</textarea>
            @if ($errors->has('body'))
                <span class="error">{{ $errors->first('body') }}</span>
            @endif
        </p>
        <p>
            <input type="submit" value="投稿">
        </p>
    </form>
</div>
@endsection

折角なので,show.blade.php と edit.blade.php もレイアウト化しておきます.

resources/views/comments/show.blade.php@extends('layouts.default')

@section('title', 'コメント')

@section('content')
<h1>コメント</h1>
<dl>
    <dt>ID:</dt>
    <dd>{{ $comment->id }}</dd>
    <dt>Title:</dt>
    <dd>{{ $comment->title }}</dd>
    <dt>Body:</dt>
    <dd>{{ $comment->body }}</dd>
</dl>
<p>
    <a href="{{ route('comments.edit', ['comment_id' => $comment->id]) }}">
        [編集]
    </a>
</p>
<div>
    <form action="{{ route('comments.destroy', ['comment_id' => $comment->id]) }}" method="post">
        @csrf
        @method('DELETE')
        <button type="submit" class="btn btn-danger">コメントの削除</button>
    </form>
</div>
@endsection
resources/views/comments/edit.blade.php@extends('layouts.default')

@section('title', 'コメント編集')

@section('content')
<h1>コメント編集</h1>
<div>
    <form method="post" action="{{ route('comments.update') }}" enctype='multipart/form-data'>
        @csrf
        @method('PATCH')
        <input type="hidden" name="comment_id" value="{{ $comment->id }}">
        <p>
            <label for="title">Title: </label>
            <input type="text" name="title" id="title" value="{{ $comment->title }}{{ old('title') }}">
            @if ($errors->has('title'))
                <span class="error">{{ $errors->first('title') }}</span>
            @endif
        </p>
        <p>
            <label for="body">Body: </label>
            <textarea name="body" id="body" rows="4" cols="50">{{ $comment->body }}{{ old('body') }}</textarea>
            @if ($errors->has('body'))
                <span class="error">{{ $errors->first('body') }}</span>
            @endif
        </p>
        <p>
            <input type="submit" value="更新">
        </p>
    </form>
</div>
@endsection

大幅な修正を施したので,自動テストを実行して正しく表示できるかも確認しておくと良いでしょう.

vagrant@ubuntu2204 comment_app $ history | grep test ⏎
  183  ls tests/
  184  ls tests/Feature/
  185  ls tests/Unit/
  186  php artisan make:test CommentsControllerTest
  187  ls tests/Feature/
  188  php artisan make:test CommentsControllerTest --unit
  189  ls tests/Unit/
  190  git add tests/Feature/CommentsControllerTest.php
  191  git commit -m'php artisan make:test CommentsControllerTest'
  194  git commit -m'php artisan make:test CommentsControllerTest --unit'
  196  php artisan test tests/Feature/ExampleTest.php
  197  php artisan test
  202  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  219  history | grep test
  220  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  222  git add tests/*
  224  git commit -m'test'
  229  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  231  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  236  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  237  php artisan test
  239  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  241  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  243  php artisan test --coverage-html /var/www/html/cv_reports/comment_app
  244  history | grep test
vagrant@ubuntu2204 comment_app $ !243 ⏎
php artisan test --coverage-html /var/www/html/cv_reports/comment_app

   PASS  Tests\Unit\CommentsControllerTest
  ✓ example                                                                0.03s

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true                                                      0.01s

   PASS  Tests\Feature\CommentsControllerTest
  ✓ comments index                                                         0.25s
  ✓ comments show 3                                                        0.03s
  ✓ comments edit 3                                                        0.03s

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response                          0.04s
  ✓ the application returns a 404 error response                           0.03s

  Tests:    7 passed (7 assertions)
  Duration: 0.49s

vagrant@ubuntu2204 comment_app $

目次に戻る