Laravel 10 入門トップページ


目次

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

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

学部の情報を表示・変更する

ここでの概要

ここでは,学部の個別情報を表示するページを作成します.また学部名などの情報を更新(変更)するフォームも作成します.更新の際には,学部が所属するキャンパスを変更できる機能も実装します.このとき,存在しない(新たな)キャンパスを登録すること拒否したり,新たなキャンパスを campuses テーブルに登録する方法についても説明します.

目次に戻る

学部情報を表示する

学部個別の情報を表示するページを作成します.まず,ルートを定義します.例えば,/faculties/1 では id = 1 である栄養学部の詳細ページを表示します.

routes/web.php(抜粋)
Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/faculties', [FacultiesController::class, 'index']) -> name('faculties.index');
Route::get('/faculties/{id}', [FacultiesController::class, 'show']) -> name('faculties.show');
Route::get('/students', [StudentsController::class, 'index']) -> name('students.index');
Route::get('/lectures', [LecturesController::class, 'index']) -> name('lectures.index');

次はコントローラに show 関数を追加します.とりあえずは URL に与えられた学部の ID だけが表示されるようにします.

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);
    }

    public function show($id)
    {
        dd($id);
    }
}

学部一覧のページとキャンパス一覧のページから学部詳細情報のページにリンクを設置します.それぞれの 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>
                <a href="{{ route('faculties.show', $faculty->id) }}">{{ $faculty->faculty }}</a>は{{ $faculty->established }}年に設置され,キャンパスは {{ $faculty->campus->campus }} です
            </li>
        @endforeach
    </ul>
</body>
</html>

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><a href="{{ route('faculties.show', $faculty->id) }}">{{ $faculty->faculty }}</a></li>
                    @endforeach
                </ul>
            </li>
        @endforeach
    </ul>
</body>
</html>

この時点でキャンパス一覧や学部一覧ページのリンクから,学部の詳細ページを開くことができるようになりました.

laravel10-2023-relationship-21.png
laravel10-2023-relationship-20.png

次は FacultiesController を編集して学部情報を実際に取得してビューに渡す処理を書きます.

app/HTTP/Controllers/FacultiesController.php(抜粋)
    public function show($id)
    {
        $faculty = Faculty::where('id', $id)
                            ->first();
        if (!$faculty) {
            return redirect('/faculties');
        }
        return view('faculties.show')
                ->with('faculty', $faculty);
    }

resources/views/faculties/show.blade.php を作成し,次のような内容にします(index.blade.php とほどんど同じなので,コピーして一部を修正するだけでも構いません).

resources/views/faculties/show.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{ $faculty->faculty }}</title>
</head>
<body>
    <h1>{{ $faculty->faculty }}</h1>
    <p>キャンパスは {{ $faculty->campus->campus }} です.</p>
</body>
</html>

これで学部の詳細情報を表示するページができました.

laravel10-2023-relationship-22.png

目次に戻る

学部情報と所属キャンパスを編集する

続いて学部情報と所属キャンパスを編集する機能を実装します.まずは,編集のためのページと実際に更新処理を行う機能のルートを定義します.

routes/web.php(抜粋)
Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/faculties', [FacultiesController::class, 'index']) -> name('faculties.index');
Route::get('/faculties/{id}', [FacultiesController::class, 'show']) -> name('faculties.show');
Route::get('/faculties/{id}/edit', [FacultiesController::class, 'edit']) -> name('faculties.edit');
Route::patch('/faculties', [FacultiesController::class, 'update']) -> name('faculties.update');
Route::get('/students', [StudentsController::class, 'index']) -> name('students.index');
Route::get('/lectures', [LecturesController::class, 'index']) -> name('lectures.index');

学部詳細ページには編集ページへのリンクを設置します.

resources/views/faculties/show.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{ $faculty->faculty }}</title>
</head>
<body>
    <h1>{{ $faculty->faculty }}</h1>
    <p>キャンパスは {{ $faculty->campus->campus }} です.</p>
    <hr>
    <p><a href="{{ route('faculties.edit', $faculty->id) }}">[学部情報の編集]</a>
</body>
</html>

コントローラには edit と update 関数を追加します.なお,update 関数は更新ボタンが押されたときにどのような情報が渡されてくるかを確認するためだけのコードを記載しておきます.まだ実際にはデータベースが更新されないことに注意してください.

app/HTTP/Controllers/FacultiesController.php(抜粋)
    public function edit($id)
    {
        $faculty = Faculty::where('id', $id)
                            ->first();
        if (!$faculty) {
            return redirect('/faculties');
        }
        return view('faculties.edit')
                ->with('faculty', $faculty);
    }

    public function update(Request $request)
    {
        dd($request);
    }

編集のためのページを作成します.resources/views/faculties ディレクトリに edit.blade.php を次のとおり作成してください.

resources/views/faculties/edit.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{ $faculty->faculty }}の編集</title>
</head>
<body>
    <h1>{{ $faculty->faculty }}の編集</h1>
    <div>
        <form method="post" action="{{ route('faculties.update') }}" enctype="multipart/form-data">
            @csrf
            {{ method_field('patch') }}
            <input type="hidden" name="id" value="{{ $faculty->id }}">
            <p>
                <label for="faculty">学部名:</label>
                <input type="text" name="faculty"
                    id="faculty"
                    value="{{ $faculty->faculty }}{{ old('faculty') }}">
            </p>
            <p>
                <label for="campus">キャンパス:</label>
                <input type="text" name="campus"
                id="campus"
                value="{{ $faculty->campus->campus }}{{ old('campus') }}">
            </p>
            <p>
                <input type="submit" value="更新">
            </p>
        </form>
    </div>
</body>
</html>

これまでの作業の結果,学部詳細ページの「学部情報の編集」リンクをクリックすると,編集画面が表示されます.編集画面では学部名と所属キャンパスの名前を入力できるようになりました.

laravel10-2023-relationship-23.png

例えば「経営学部」を「経営学部経営学科DS専攻」に書き換え,キャンパスを「KAC」に書き換えて「更新」ボタンを押下します.その結果,入力された情報が $request パラメータに含まれて update 関数に渡されます.dd() 関数では格納された内容を確認することができます.なお,フォームには「学部名」と「キャンパス」のコントローラしか見えていませんが,学部の id の情報も hidden として存在していることに注意してください.

laravel10-2023-relationship-24.png

では実際にデータベースの更新を行う処理を update 関数に記載します.なお,ここでは存在しないキャンパス名を入力した場合には一切の変更を加えないようにしています.また,update 関数内で Campus:: を利用するために,コントローラの先頭で use App\Models\Campus; を宣言していることにも注意してください.

app/HTTP/Controllers/FacultiesController.php(抜粋)
<?php

namespace App\Http\Controllers;

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

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

    public function update(Request $request)
    {
        // 掲示板の例を参考にここで Validation を記載しよう(ここでは省略します.)

        $faculty = Faculty::where('id', $request->id)
                            ->first();
        $faculty->faculty = $request->faculty;
        $campus = Campus::where('campus', $request->campus)->first();
        if (!$campus) {
            // 未知のキャンパスなので,一切更新せずに戻る
            return redirect()->route('faculties.show', $request->id);
        }
        // $faculty に campus_id をセットする
        $faculty->campus_id = $campus->id;
        // データベースを更新する
        $faculty->save();
        return redirect()->route('faculties.show', $request->id);
    }
}

「経営学部」を「経営学部経営学科DS専攻」に,「KPC」を「KAC」に書き換えて「更新」ボタンを押下します.

laravel10-2023-relationship-25.png

学部名と所属キャンパスの情報が更新されました.

laravel10-2023-relationship-26.png

次に,キャンパスを campuses テーブルに存在しない「ポートアイランドキャンパス」に書き換えて「更新」を押下します.

laravel10-2023-relationship-27.png

このときにはデータは更新されませんでした.(ユーザが認識できるようにフラッシュメッセージなどを使ってエラーを表示すると良いでしょう)

laravel10-2023-relationship-28.png

その後,所属キャンパスを「KPC」に戻す操作まで行ったときに,その都度 SQLite でデータベースの内容を確認すると,次のような結果になりました.所属キャンパスを更新すると「campus_id」の値が更新され,それと同時に「updated_at」に更新日時が記録されていることに注意してください.

vagrant@ubuntu2204 laravelRelationship $ pwd ⏎
/home/vagrant/Documents/laravel/laravelRelationship
vagrant@ubuntu2204 laravelRelationship $ sqlite3 database/database.sqlite ⏎
SQLite version 3.38.2 2022-03-26 13:51:10
Enter ".help" for usage hints.
sqlite> .tables ⏎
campuses                lectures                students
faculties               migrations              users
failed_jobs             password_reset_tokens
lecture_student         personal_access_tokens
sqlite> .headers ON ⏎
sqlite> SELECT * FROM faculties; ⏎ # 更新前
id|faculty|established|campus_id|created_at|updated_at
1|栄養学部|1966|1||
2|法学部|1967|2||
3|経済学部|1967|1||
4|薬学部|1972|2||
5|人文学部|2004|1||
6|経営学部|2004|2||
7|総合リハビリテーション学部|2005|1||
8|現代社会学部|2014|2||
9|グローバル・コミュニケーション学部|2015|2||
10|心理学部|2018|1||
sqlite> SELECT * FROM faculties; ⏎ # 最初の更新後
id|faculty|established|campus_id|created_at|updated_at
1|栄養学部|1966|1||
2|法学部|1967|2||
3|経済学部|1967|1||
4|薬学部|1972|2||
5|人文学部|2004|1||
6|経営学部経営学科DS専攻|2004|1||2023-10-17 18:23:56
7|総合リハビリテーション学部|2005|1||
8|現代社会学部|2014|2||
9|グローバル・コミュニケーション学部|2015|2||
10|心理学部|2018|1||
sqlite> SELECT * FROM faculties; ⏎ # 2回目の更新後
id|faculty|established|campus_id|created_at|updated_at
1|栄養学部|1966|1||
2|法学部|1967|2||
3|経済学部|1967|1||
4|薬学部|1972|2||
5|人文学部|2004|1||
6|経営学部経営学科DS専攻|2004|2||2023-10-17 18:24:45
7|総合リハビリテーション学部|2005|1||
8|現代社会学部|2014|2||
9|グローバル・コミュニケーション学部|2015|2||
10|心理学部|2018|1||
sqlite> .exit ⏎
vagrant@ubuntu2204 laravelRelationship $

目次に戻る

学部情報の編集により新規キャンパスを追加する

上の例では,campuses テーブルに存在しない「ポートアイランドキャンパス」のような値で更新しようとしても,一切の更新を行わないという設計でした.しかしながら,場合によっては,学部の変更と同時に新たなキャンパスが設置されたものとし,campuses テーブルに新たなレコードを追加したいというようなケースもあります.例えば,新たなキャンパス「KPC2」が設置され,経営学部経営学科DS専攻だけを「KPC2」に移動させることを考えます.このような場合,まず,campuses テーブルに新たなレコードを追加し,その ID を取得して,faculties の当該レコードを更新すれば,リレーションシップの参照整合性を保つことができるようになるでしょう.この処理をコントローラに記載します.

app/HTTP/Controllers/CampusesController.php(抜粋)
    public function update(Request $request)
    {
        // 掲示板の例を参考にここで Validation を記載しよう(ここでは省略します.)

        $faculty = Faculty::where('id', $request->id)
                            ->first();
        $faculty->faculty = $request->faculty;
        $campus = Campus::where('campus', $request->campus)->first();
        if (!$campus) {
            // 未知のキャンパスなので,新規に登録する
            $new_campus = new Campus();
            $new_campus->campus = $request->campus;
            $new_campus->save();  // campuses テーブルに新規登録する
            $faculty->campus_id = $new_campus->id;   // 新規登録したIDをセットする
        } else {
            // すでに存在するキャンパスの場合は取得したIDをセットする
            $faculty->campus_id = $campus->id;
        }
        // faculties テーブルを更新する
        $faculty->save();
        return redirect()->route('faculties.show', $request->id);
    }

キャンパスを「KPC2」に変更して「更新」ボタンを押下します.

laravel10-2023-relationship-29.png

所属キャンパスが「KPC2」に更新されました.(もちろん,新たなキャンパスを登録して良いかというのは別問題です)

laravel10-2023-relationship-30.png
laravel10-2023-relationship-31.png

キャンパス一覧ページも確認します.

laravel10-2023-relationship-32.png

この更新作業の途中に随時 SQLite でデータベースの内容を確認すると,次のようになりました.所属キャンパスを「KPC2」に変更したときには,まず,campuses テーブルに新たなレコードが追加され,そのレコードの ID が faculties テーブルの外部キーとして設定されていることがわかるはずです.

vagrant@ubuntu2204 laravelRelationship $ sqlite3 database/database.sqlite ⏎
SQLite version 3.38.2 2022-03-26 13:51:10
Enter ".help" for usage hints.
sqlite> .tables ⏎
campuses                lectures                students
faculties               migrations              users
failed_jobs             password_reset_tokens
lecture_student         personal_access_tokens
sqlite> .headers ON ⏎
sqlite> SELECT * FROM faculties; ⏎ # 更新前
id|faculty|established|campus_id|created_at|updated_at
1|栄養学部|1966|1||
2|法学部|1967|2||
3|経済学部|1967|1||
4|薬学部|1972|2||
5|人文学部|2004|1||
6|経営学部経営学科DS専攻|2004|2||2023-10-17 18:24:45
7|総合リハビリテーション学部|2005|1||
8|現代社会学部|2014|2||
9|グローバル・コミュニケーション学部|2015|2||
10|心理学部|2018|1||
sqlite> SELECT * FROM campuses; ⏎ # 更新前
id|campus|created_at|updated_at
1|KAC||
2|KPC||
sqlite> SELECT * FROM faculties; ⏎ # 更新後
id|faculty|established|campus_id|created_at|updated_at
1|栄養学部|1966|1||
2|法学部|1967|2||
3|経済学部|1967|1||
4|薬学部|1972|2||
5|人文学部|2004|1||
6|経営学部経営学科DS専攻|2004|3||2023-10-17 18:29:11
7|総合リハビリテーション学部|2005|1||
8|現代社会学部|2014|2||
9|グローバル・コミュニケーション学部|2015|2||
10|心理学部|2018|1||
sqlite> SELECT * FROM campuses; ⏎ # 更新後
id|campus|created_at|updated_at
1|KAC||
2|KPC||
3|KPC2|2023-10-17 18:29:11|2023-10-17 18:29:11
sqlite> .exit ⏎
vagrant@ubuntu2204 laravelRelationship $

目次に戻る