Laravel 10 入門トップページ


目次

  1. 概要
  2. プロジェクトの作成と初期設定
  3. 一対多のリレーションシップ
  4. 多対多のリレーションシップ
  5. ビューを使った表示
  6. 学部の情報を表示・変更する
  7. キャンパスの情報を表示・変更・削除する
  8. 学生の情報を表示・変更・削除する

Laravel でリレーションシップを使いこなす

ビューを使った表示

トップページ

まず,トップページ welcome.blade.php を編集して,キャンパス,学部,学生,講義の各一覧ページへのリンクを作成します.トップページでは Tailwind CSS を利用している関係で,多くのクラスが指定されて見にくくなっていますが,43行目から61行目の <a>〜</a> タグで囲われた範囲が一つのブロックになります.このブロックを4個複製して適宜修正すると良いでしょう.

laravel10-2023-relationship-11.png

resources/views/welcome.blade.php(一部省略)<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />

        <!-- Styles -->
        <style>
            /* ! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com */*,  (中略)
        </style>
    </head>
    <body class="antialiased">
        <div class="relative sm:flex sm:justify-center sm:items-center min-h-screen bg-dots-darker bg-center bg-gray-100 dark:bg-dots-lighter dark:bg-gray-900 selection:bg-red-500 selection:text-white">
            @if (Route::has('login'))
                <div class="sm:fixed sm:top-0 sm:right-0 p-6 text-right z-10">
                    @auth
                        <a href="{{ url('/home') }}" class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Home</a>
                    @else
                        <a href="{{ route('login') }}" class="font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Log in</a>

                        @if (Route::has('register'))
                            <a href="{{ route('register') }}" class="ml-4 font-semibold text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">Register</a>
                        @endif
                    @endauth
                </div>
            @endif

            <div class="max-w-7xl mx-auto p-6 lg:p-8">
                <div class="flex justify-center">
                    <svg viewBox="0 0 62 65" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto bg-gray-100 dark:bg-gray-900">
                        <path d="M61.8548 (中略) 47.987Z" fill="#FF2D20"/>
                    </svg>
                </div>

                <div class="mt-16">
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-8">
                        <a href="/campuses" class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
                            <div>
                                <div class="h-16 w-16 bg-red-50 dark:bg-red-800/20 flex items-center justify-center rounded-full">
                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="w-7 h-7 stroke-red-500">
                                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
                                    </svg>
                                </div>

                                <h2 class="mt-6 text-xl font-semibold text-gray-900 dark:text-white">キャンパス</h2>

                                <p class="mt-4 text-gray-500 dark:text-gray-400 text-sm leading-relaxed">
                                    キャンパスの一覧を表示します
                                </p>
                            </div>

                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="self-center shrink-0 stroke-red-500 w-6 h-6 mx-6">
                                <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
                            </svg>
                        </a>

                        <a href="/faculties" class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
                            <div>
                                <div class="h-16 w-16 bg-red-50 dark:bg-red-800/20 flex items-center justify-center rounded-full">
                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="w-7 h-7 stroke-red-500">
                                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
                                    </svg>
                                </div>

                                <h2 class="mt-6 text-xl font-semibold text-gray-900 dark:text-white">学部</h2>

                                <p class="mt-4 text-gray-500 dark:text-gray-400 text-sm leading-relaxed">
                                    学部の一覧を表示します
                                </p>
                            </div>

                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="self-center shrink-0 stroke-red-500 w-6 h-6 mx-6">
                                <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
                            </svg>
                        </a>

                        <a href="/students" class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
                            <div>
                                <div class="h-16 w-16 bg-red-50 dark:bg-red-800/20 flex items-center justify-center rounded-full">
                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="w-7 h-7 stroke-red-500">
                                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
                                    </svg>
                                </div>

                                <h2 class="mt-6 text-xl font-semibold text-gray-900 dark:text-white">学生</h2>

                                <p class="mt-4 text-gray-500 dark:text-gray-400 text-sm leading-relaxed">
                                    学生の一覧を表示します
                                </p>
                            </div>

                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="self-center shrink-0 stroke-red-500 w-6 h-6 mx-6">
                                <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
                            </svg>
                        </a>

                        <a href="/lectures" class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
                            <div>
                                <div class="h-16 w-16 bg-red-50 dark:bg-red-800/20 flex items-center justify-center rounded-full">
                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="w-7 h-7 stroke-red-500">
                                        <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
                                    </svg>
                                </div>

                                <h2 class="mt-6 text-xl font-semibold text-gray-900 dark:text-white">講義</h2>

                                <p class="mt-4 text-gray-500 dark:text-gray-400 text-sm leading-relaxed">
                                    講義の一覧を表示します
                                </p>
                            </div>

                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="self-center shrink-0 stroke-red-500 w-6 h-6 mx-6">
                                <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12h15m0 0l-6.75-6.75M19.5 12l-6.75 6.75" />
                            </svg>
                        </a>

                    </div>
                </div>

                <div class="flex justify-center mt-16 px-0 sm:items-center sm:justify-between">
                    <div class="text-center text-sm text-gray-500 dark:text-gray-400 sm:text-left">
                        <div class="flex items-center gap-4">
                            <a href="https://github.com/sponsors/taylorotwell" class="group inline-flex items-center hover:text-gray-700 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-red-500">
                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" class="-mt-px mr-1 w-5 h-5 stroke-gray-400 dark:stroke-gray-600 group-hover:stroke-gray-600 dark:group-hover:stroke-gray-400">
                                    <path stroke-linecap="round" stroke-linejoin="round" d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z" />
                                </svg>
                                Sponsor
                            </a>
                        </div>
                    </div>

                    <div class="ml-4 text-center text-sm text-gray-500 dark:text-gray-400 sm:text-right sm:ml-0">
                        Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

目次に戻る

キャンパス一覧

app/HTTP/Controllers/CampusesController.php<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Campus;     // 追加

class CampusesController extends Controller
{
    public function index()
    {
        $campuses = Campus::get();
        return view('campuses.index')
                ->with('campuses', $campuses);
    }
}

次に,ビューの雛形を作成します.resources/views ディレクトリ以下に campuses ディレクトリを作成し,その中に index.blade.php を設置します.index.blade.php には次のようなコードを記載します.

resources/views/campuses/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>キャンパス一覧</title>
</head>
<body>
    <h1>キャンパス一覧</h1>
</body>
</html>

この状態では見出しが表示されるだけです.

laravel10-2023-relationship-12.png

コントローラで取得したキャンパスの一覧を箇条書きで表示します.

resources/views/campuses/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>キャンパス一覧</title>
</head>
<body>
    <h1>キャンパス一覧</h1>
    <ul>
        @foreach ($campuses as $campus)
            <li>{{ $campus->campus }}</li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-13.png

さらに一対多のリレーションシップを辿って各キャンパスに所属する学部の一覧も取得してみます.すでに Campus モデルに faculties メソッドを定義しているので,それを呼び出すだけです.

resources/views/campuses/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>キャンパス一覧</title>
</head>
<body>
    <h1>キャンパス一覧</h1>
    <ul>
        @foreach ($campuses as $campus)
            <li>
                {{ $campus->campus }}
                <ul>
                    @foreach ($campus->faculties as $faculty)
                        <li>{{ $faculty->faculty }}</li>
                    @endforeach
                </ul>
            </li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-14.png

目次に戻る

学部一覧

今度は学部の一覧ページのビューを作成しよう.まず,FacultiesController を編集し,コントローラからビューを呼び出すように変更します.

app/HTTP/Controllers/FacultiesController.php<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Faculty;     // 追加

class FacultiesController extends Controller
{
    public function index()
    {
        $faculties = Faculty::get();
        return view('faculties.index')
                ->with('faculties', $faculties);
    }
}

次に,ビューを作成します.resources/views ディレクトリ以下に faculties ディレクトリを作成し,その中に index.blade.php を設置します.この index.blade.php の内容は次のとおりです.

resources/views/faculties/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>学部一覧</title>
</head>
<body>
    <h1>学部一覧</h1>
    <ul>
        @foreach ($faculties as $faculty)
            <li>{{ $faculty->faculty }}</li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-15.png

さらに設置年度と所属キャンパスの情報も取得して表示します.やはり Faculty モデルに campus メソッドを定義しているので,それを読み出すだけで所属キャンパスの情報を取得することができます.

resources/views/faculties/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>学部一覧</title>
</head>
<body>
    <h1>学部一覧</h1>
    <ul>
        @foreach ($faculties as $faculty)
            <li>
                {{ $faculty->faculty }}は{{ $faculty->established }}年に設置され,キャンパスは {{ $faculty->campus->campus }} です
            </li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-16.png

目次に戻る

学生一覧

今度は学生一覧のビューを作成します.まずコントローラを編集してビューを呼び出すようにします.

app/HTTP/Controllers/StudentsController.php<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Student;

class StudentsController extends Controller
{
    public function index()
    {
        $students = Student::get();
        return view('students.index')
                ->with('students', $students);
    }
}

次にビューを作成します.キャンパス一覧や学部一覧と同様に resources/views ディレクトリ以下に students ディレクトリを作成し,その中に次のような index.blade.php を設置します.

resources/views/students/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>学生一覧</title>
</head>
<body>
    <h1>学生一覧</h1>
    <ul>
        @foreach ($students as $student)
            <li>{{ $student->id }} : {{ $student->name }}</li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-17.png

各学生の履修講義も取得してみます.Student モデルに lectures メソッドを定義しているので,リレーションシップを辿ってすべての履修講義を取得することができます.

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>学生一覧</title>
</head>
<body>
    <h1>学生一覧</h1>
    <ul>
        @foreach ($students as $student)
            <li>
                {{ $student->id }} : {{ $student->name }}
                <ul>
                    @foreach ($student->lectures as $lecture)
                        <li>{{ $lecture->name }}</li>
                    @endforeach
                </ul>
            </li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-18.png

目次に戻る

講義一覧

最後に講義の一覧を取得します.方法は学生一覧とほぼ同じです.Lecture モデルに定義した students メソッドを利用します.

app/HTTP/Controllers/LecturesController.php<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Lecture;

class LecturesController extends Controller
{
    public function index()
    {
        $lectures = Lecture::get();
        return view('lectures.index')
                ->with('lectures', $lectures);
    }
}

resources/views/lectures/index.blade.php<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>講義一覧</title>
</head>
<body>
    <h1>講義一覧</h1>
    <ul>
        @foreach ($lectures as $lecture)
            <li>
                {{ $lecture->name }}
                <ul>
                    @foreach ($lecture->students as $student)
                        <li>{{ $student->id }} : {{ $student->name }}</li>
                    @endforeach
                </ul>
            </li>
        @endforeach
    </ul>
</body>
</html>

laravel10-2023-relationship-19.png

目次に戻る