あちゃまWEB >

Laravelのリレーション操作

ModelControllerView
プライマリキー同士でリレーションする例

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>

  

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

WordPress情報


WEB開発


その他