ここでは,個別のキャンパス情報を表示するページを作成します.また,キャンパス情報を更新(変更)するためのフォームも作成します.特に,あるキャンパスの情報を削除した時に,そのキャンパスに所属する情報を連鎖的に削除する方法についても説明します.
ここでは,個別のキャンパス情報を表示するページを作成します.このためにはまずルート情報を定義します.例えば,/campuses/1 という URI でアクセスされた場合には ID = 1 のキャンパスである KAC の情報を表示します.
routes/web.php(抜粋)
Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/campuses/{id}', [CampusesController::class, 'show']) -> name('campuses.show');
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');
次にコントローラに show 関数を追加します.まずは引数だけを表示するようにします.
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);
}
public function show($id)
{
dd($id);
}
}
学部の一覧ページ /faculties と キャンパスの一覧ページ /campuses にキャンパス個別ページへのリンクを設置します.それぞれの 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 }}年に設置され,キャンパスは <a href="{{ route('campuses.show', $faculty->campus->id) }}">{{ $faculty->campus->campus }}</a> です
</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>
<a href="{{ route('campuses.show', $campus->id) }}">
{{ $campus->campus }}
</a>
<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>
キャンパス一覧ページや学部一覧ページから「KAC」のリンクを押下すると,ID だけが確認できました.
次は,CampusesController の show 関数を編集して,学部情報を実際に取得し,ビューに渡すという処理を書きます.
app/HTTP/Controllers/CampusesController.php(抜粋)
public function show($id)
{
$campus = Campus::where('id', $id)
->first();
if (!$campus) {
return redirect('/campuses');
}
return view('campuses.show')
->with('campus', $campus);
}
さらにビューを作成します.具体的には resources/views/campuses/show.blade.php を作成して,次のような内容を記載します.index.blade.php とほどんど同じなのでコピーして一部を書き換えても構いません.
resources/views/campuses/show.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ $campus->campus }}</title>
</head>
<body>
<h1>{{ $campus->campus }}</h1>
<ul>
@foreach ($campus->faculties as $faculty)
<li><a href="{{ route('faculties.show', $faculty->id) }}">{{ $faculty->faculty }}</a></li>
@endforeach
</ul>
</body>
</html>
これでキャンパス詳細情報を表示するページができました.
次はキャンパス詳細情報のページから編集ページへのリンクを作成して編集作業ができるような機能を実装します.まずはルートの定義を行います.ここでは,編集画面を表示するためのルートの定義と,編集画面で「更新」ボタンを押した後の処理を行うためのルートの定義を追加します.
routes/web.php(抜粋)
Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/campuses/{id}', [CampusesController::class, 'show']) -> name('campuses.show');
Route::get('/campuses/{id}/edit', [CampusesController::class, 'edit']) -> name('campuses.edit');
Route::patch('/campuses', [CampusesController::class, 'update']) -> name('campuses.update');
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');
コントローラには編集画面表示のための edit 関数と更新処理を行う update 関数を定義します.更新処理については,まだ実際には更新せずフォームから送信された情報を表示する機能だけを入れておきます.
app/HTTP/Controllers/CampusesController.php(抜粋)
public function edit($id)
{
$campus = Campus::where('id', $id)
->first();
if (!$campus) {
return redirect('/campuses');
}
return view('campuses.edit')
->with('campus', $campus);
}
public function update(Request $request)
{
dd($request);
}
個別キャンパス情報の表示ページに編集画面へのリンクを設置します.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ $campus->campus }}</title>
</head>
<body>
<h1>{{ $campus->campus }}</h1>
<ul>
@foreach ($campus->faculties as $faculty)
<li><a href="{{ route('faculties.show', $faculty->id) }}">{{ $faculty->faculty }}</a></li>
@endforeach
</ul>
<hr>
<p><a href="{{ route('campuses.edit', $campus->id) }}">[キャンパス情報の編集]</a></p>
</body>
</html>
さらに編集画面を設計します.適切なフォルダに新しいファイル edit.blade.php を作成して,次の内容にしてください.
resources/views/campuses/edit.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ $campus->campus }}の編集</title>
</head>
<body>
<h1>{{ $campus->campus }}の編集</h1>
<div>
<form method="post" action="{{ route('campuses.update') }}" enctype="multipart/form-data">
@csrf
{{ method_field('patch') }}
<input type="hidden" name="id" value="{{ $campus->id }}">
<p>
<label for="campus">キャンパス名:</label>
<input type="text" name="campus"
id="campus"
value="{{ $campus->campus }}{{ old('campus') }}">
</p>
<p>
<input type="submit" value="更新">
</p>
</form>
</div>
</body>
</html>
ここまでの状態での動作を確認します.個別学部の表示ページには「キャンパス情報の編集」リンクがあるので,それをクリックします.
「KAC」の編集画面が表示されました.
キャンパス名を「有瀬キャンパス」に書き換えて「更新ボタン」をクリックします.
フォームに入力された情報などが $request
に格納されていることがわかります.この時に不正な書き込みを防止するためのトークンが仕込まれていることにも注意してください.
では,実際にデータベースを更新するコードを入力します.
app/HTTP/Controllers/CampusesController.php(抜粋)
public function update(Request $request)
{
// 掲示板の例を参考にここで Validation を記載しよう(ここでは省略します.)
$campus = Campus::where('id', $request->id)
->first();
$campus->campus = $request->campus;
$campus->save();
return redirect()->route('campuses.show', $request->id);
}
実際に「KAC」を「有瀬キャンパス」に更新した結果です.
もちろんキャンパス一覧ページでも更新内容が確認できるはずです.
次は,キャンパス情報を削除する機能を実装します.なお,あるキャンパスの情報を削除するとそのキャンパスに所属している学部の情報も連鎖的に削除することにします(連鎖的に削除しない方法ももちろん実現可能です).まずは削除のためのルートを定義します.
routes/web.php(抜粋)
Route::get('/campuses', [CampusesController::class, 'index']) -> name('campuses.index');
Route::get('/campuses/{id}', [CampusesController::class, 'show']) -> name('campuses.show');
Route::get('/campuses/{id}/edit', [CampusesController::class, 'edit']) -> name('campuses.edit');
Route::patch('/campuses', [CampusesController::class, 'update']) -> name('campuses.update');
Route::delete('/campuses/{id}', [CampusesController::class, 'destroy']) -> name('campuses.destroy');
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/campuses/show.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{{ $campus->campus }}</title>
</head>
<body>
<h1>{{ $campus->campus }}</h1>
<ul>
@foreach ($campus->faculties as $faculty)
<li><a href="{{ route('faculties.show', $faculty->id) }}">{{ $faculty->faculty }}</a></li>
@endforeach
</ul>
<hr>
<p><a href="{{ route('campuses.edit', $campus->id) }}">[キャンパス情報の編集]</a></p>
<div>
<form action="{{ route('campuses.destroy', $campus->id )}}" method="post">
@csrf
{{ method_field('DELETE') }}
<button>キャンパスの削除</button>
</form>
</div>
</body>
</html>
コントローラに destroy メソッドを作成し,指定したレコードをテーブルから削除するコードを入力します.
public function destroy($id)
{
$campus = Campus::where('id', $id)
->first();
if (!$campus) {
return redirect('/campuses');
}
$campus->delete();
return redirect('/campuses');
}
これから「KPC」のレコード削除に関する実験を行うので,その前にデータベースをロールバック,マイグレーション,シードの投入を実行してデータベースをリセットしておきます.
vagrant@ubuntu2204 laravelRelationship $ php artisan migrate:rollback; php artisan migrate; php artisan db:seed ⏎
まず,学部一覧ページを表示して10の学部が存在することを確認します.
次に,キャンパス一覧のページでも2つのキャンパスに合計10の学部があることを確認します.
「KPC」のページを表示します.KPCには5つの学部が所属しています.ここで,「キャンパス情報の削除」ボタンを押して,KPCのレコードを削除します.
「KPC」のレコードを削除した結果,キャンパス「KAC」だけになりました.
それと同時に,学部テーブルからからKPCに所属していた学部がすべて連鎖的に削除されていることも確認できました.
今の「KPC」を削除した作業の途中で適宜 SQLite でデータベースの内容を確認したところ,次のような結果になりました.
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 campuses; ⏎ # KPCの削除前 id|campus|created_at|updated_at 1|KAC|| 2|KPC|| sqlite> SELECT * FROM faculties; ⏎ # KPCの削除前 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 campuses; ⏎ # KPCの削除後 id|campus|created_at|updated_at 1|KAC|| sqlite> SELECT * FROM faculties; ⏎ # KPCの削除後 id|faculty|established|campus_id|created_at|updated_at 1|栄養学部|1966|1|| 3|経済学部|1967|1|| 5|人文学部|2004|1|| 7|総合リハビリテーション学部|2005|1|| 10|心理学部|2018|1|| sqlite> .exit ⏎ vagrant@ubuntu2204 laravelRelationship $
なお,ここでの例では faculties テーブルのマイグレーションで onDelete('cascade')
を指定しました.キャンパスと学部は「一対多」の関係ですが,一側の campuses テーブルでの削除によって,多側テーブルである faculties テーブルで連鎖的な削除が行われました.CASCADE 以外にも,RESTRICT, SET NULL, NO ACTION などが利用できます.詳細は例えばこのWebページなどで確認してください.