| Model | Controller | View |
プライマリキー同士でリレーションする例 |
class Post extends Model
{
// postsテーブルの user_id (外部キー) を通じて
// usersテーブルの id (主キー) を参照するリレーション
public function user(): BelongsTo
{
// 'user'というリレーション名は、自動的に user_id を探します。
// もし外部キーが 'author_id' などカスタム名なら、以下のように指定します。
// return $this->belongsTo(User::class, 'author_id');
return $this->belongsTo(User::class);
}
}
|
class PostController extends Controller
{
public function index()
{
// 1. Eager Loading (withメソッド):
// Postモデルを全て取得し、同時にリレーション user もデータベースから読み込む
// これにより、ビューでのループ時に都度クエリが発行されるのを防ぎます。
$posts = Post::with('user')->get();
// 2. Dynamic Property: 1件だけ取得する場合はプロパティとしてアクセス可能
// $singlePost = Post::find(1);
// $authorName = $singlePost->user->name; // ユーザー情報にアクセス
return view('posts.index', compact('posts'));
}
}
|
投稿一覧
@foreach ($posts as $post)
{{ $post->title }}
投稿者:
{{-- リレーション user をプロパティとして参照 --}}
{{ $post->user->name }}
({{ $post->user->email }})
{{ $post->body }}
@endforeach
|
親から子への参照でリレーションする例 |
class User extends Model
{
// 自身 (usersテーブルの id) を主キーとして
// Post::class の外部キー (post_id) を参照するリレーション
public function posts(): HasMany
{
// 'posts'というリレーション名は、自動的に post_id を探します。
// もし外部キーが 'author_id' などカスタム名なら、以下のように指定します。
// return $this->hasMany(Post::class, 'author_id');
return $this->hasMany(Post::class);
}
}
|
class UserController extends Controller
{
public function show(User $user)
{
// 1. Eager Loading (withメソッド):
// 特定のユーザーを取得し、同時にリレーション posts も読み込む
$user = User::where('id', $user->id)
->with('posts')
->first();
return view('users.show', compact('user'));
}
}
|
{{ $user->name }}の投稿
@if ($user->posts->isEmpty())
まだ投稿はありません。
@else
@foreach ($user->posts as $post)
{{-- リレーション posts の各要素(Postモデル)の属性を参照 --}}
{{ $post->title }}
{{ $post->body }}
@endforeach
@endif
|
複数のリレーションを指定する例 |
/** ① snPlaceID (実施場所コード) から会場情報を取得するリレーション */
public function placeKaijo(): BelongsTo
{
// 外部キー: snPlaceID, 参照先のキー: id (KaijoモデルのPKと仮定)
return $this->belongsTo(Kaijo::class, 'snPlaceID');
}
/** ② snClassRoomID (教室コード) から会場情報を取得するリレーション */
public function classroomKaijo(): BelongsTo
{
// 外部キー: snClassRoomID, 参照先のキー: id (KaijoモデルのPKと仮定)
return $this->belongsTo(classroom::class, 'snClassRoomID');
}
|
// 運営者情報取得
$user = Auth::user();
// セミナー情報取得
$seminar = seminar::findOrFail($id);
// 2. seminerdate テーブルから、このセミナーIDに関連する全ての実施日情報を取得
$SeminerDate = SeminerDate::where('seminar_id', $seminar->id)
// snPlaceIDでKaijoを検索するリレーションをEagerロード
->with('placeKaijo') // ・・・①
->with('classroomKaijo') // ・・・②
->get();
return view('seminer.semEdit',
compact('user', 'seminar', 'SeminerDate'));
|
<x-rTextbox name="spSeminerName" value="{{ $seminar->snSeminerName }}" required> 講座名 </x-rTextbox>
@foreach ($SeminerDate as $date)
<tr name="jissiLine">
<td>
<input name="subject[]" type="text" class="InputBox_text txtWidth_9" value="{{ $date->subject }}" alt="実施タイトル">
</td>
<td>
<input name="snSeminerDate[]" type="date" class="InputBox_text txtWidth_8" value="{{ $date->snSeminerDate }}" alt="実施日"><br>
</td>
<td>
<input name="snPlace[]" class="InputBox_text txtWidth_10" value="{{ $date->placeKaijo->kjKaijoName ?? '会場情報なし'}}" alt="会場名"><br>
<input name="snClassRoom[]" class="InputBox_text txtWidth_10" value="{{ $date->classroomKaijo->crName ?? '教室情報なし' }}" alt="教室名">
</td>
<td>
<input name="snBosyu[]" type="number" class="InputBox_text txtWidth_5" value="{{ $date->snBosyu }}" alt="募集" min="1">
</td>
</tr>
@endforeach
|
リレーションのネストの例 |
class seminar extends Model
{
protected $table = 'seminars';
:
public function user(): BelongsTo
{ // ①
return $this->belongsTo(User::class, 'snUnei');
}
public function students(): HasMany
{ // ②
return $this->hasMany(student::class, 'rqSeminer');
}
public function typKouza()
{ // ③ snType (講座タイプID) から typkouzas テーブルの情報を取得するリレーション
return $this->belongsTo(typkouza::class, 'snType');
}
public function seminerDates()
{ // ④ seminar_idから seminerdate テーブルの情報を取得するリレーション
return $this->hasMany(seminerdate::class, 'seminar_id');
}
}
class seminerdate extends Model
{
// 使用するテーブル名を明示的に設定する
protected $table = 'seminerdate';
:
public function placeKaijo(): BelongsTo
{ // ⑤ 外部キー: snPlaceID, 参照先のキー: id (KaijoモデルのPKと仮定)
return $this->belongsTo(Kaijo::class, 'snPlaceID');
}
public function classroomKaijo(): BelongsTo
{ // ⑥ snClassRoomID (教室コード) から会場情報を取得するリレーション
return $this->belongsTo(classroom::class, 'snClassRoomID');
}
public function seminar(): BelongsTo
{ // ⑦ seminar_id から親のSeminarを取得するリレーション
return $this->belongsTo(Seminar::class, 'seminar_id');
}
}
|
$seminars = Seminar::whereDate('snSeminerDate', '>=', $today) // 要件1: 実施日($todayから$endDateの範囲)
->whereDate('snSeminerDate', '<=', $endDate)
->orderBy('snSeminerDate') // 要件2: snSeminerDate順に表示
->with([
'user', // ① seminar.snUnei で User を検索
'students', // ② 参加学生 (既存)
'typKouza', // ③ seminar.snType で typKouza を検索
// ネストされたリレーション (ドット記法を使用)
'seminerDates', // ④ seminarのidを持つseminardateを全て検索
'seminerDates.placeKaijo', // ⑤ seminerdate.snPlaceID で Kaijo を検索
'seminerDates.classroomKaijo', // ⑥ seminerdate.snClassRoomID で Kaijo を検索
])
->get();
|
<div class="space-y-8">
@foreach($seminars as $seminar)
<div class="bg-white shadow-md rounded-lg overflow-hidden border border-gray-200">
<!-- セミナー基本情報ヘッダー -->
<div class="bg-indigo-700 p-4 text-white">
<div class="flex justify-between items-center">
<h2 class="text-xl font-bold">
{{ $seminar->post_title }}
<span class="text-sm font-normal ml-2">[{{ $seminar->typKouza->name ?? 'タイプ不明' }}]</span>
</h2>
<span class="bg-white text-indigo-700 px-3 py-1 rounded-full text-sm font-bold">
ID: {{ $seminar->ID }}
</span>
</div>
</div>
<div class="p-6 grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- 左側:詳細情報 -->
<div class="col-span-2">
<h3 class="font-bold text-gray-700 border-b mb-3">セミナー内容</h3>
<p class="text-gray-600 mb-4 whitespace-pre-wrap">{{ $seminar->post_content ?: '(内容の記載はありません)' }}</p>
<!-- 運営者・講師情報 (リレーション ①) -->
<div class="bg-gray-50 p-3 rounded">
<p class="text-sm text-gray-500">運営・担当者</p>
<p class="font-medium text-gray-800">{{ $seminar->user->name ?? '未設定' }}</p>
</div>
</div>
<!-- 右側:日程と会場情報 (リレーション ④, ⑤, ⑥) -->
<div class="bg-indigo-50 p-4 rounded-lg">
<h3 class="font-bold text-indigo-900 mb-3 flex items-center">
<i class="fas fa-calendar-alt mr-2"></i> 開催スケジュール
</h3>
<ul class="space-y-4">
@forelse($seminar->seminerDates as $date)
<li class="border-l-4 border-indigo-400 pl-3">
<div class="font-bold text-gray-800">
{{ \Carbon\Carbon::parse($date->snDate)->format('Y/m/d H:i') }}〜
</div>
<div class="text-sm text-gray-600">
<!-- 会場 (⑤) / 教室 (⑥) -->
<i class="fas fa-map-marker-alt mr-1"></i>
{{ $date->placeKaijo->name ?? '会場未定' }}
<span class="text-indigo-600 font-medium">
({{ $date->classroomKaijo->name ?? '教室未設定' }})
</span>
</div>
</li>
@empty
<li class="text-gray-500 text-sm italic">日程は未定です</li>
@endforelse
</ul>
<!-- 参加学生数 (リレーション ②) -->
<div class="mt-6 pt-4 border-t border-indigo-200">
<div class="flex justify-between items-center">
<span class="text-sm font-bold text-gray-700">現在の申込者</span>
<span class="text-lg font-black text-indigo-700">{{ $seminar->students->count() }} 名</span>
</div>
<div class="mt-2 text-right">
<a href="#" class="text-xs text-indigo-600 hover:underline">申込者リストを確認 →</a>
</div>
</div>
</div>
</div>
</div>
@endforeach
</div>
|