iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Modern Web

Laravel 30天速成筆記系列 第 12

【Day12】Laravel Model 關聯(Many-to-Many、HasManyThrough)

  • 分享至 

  • xImage
  •  

昨天我們學了一對一(One-to-One)和一對多(One-to-Many)今天來了解稍微進階的兩種關係:多對多(Many-to-Many)HasManyThrough


多對多(Many-to-Many)

什麼是多對多?

  • 學生(Student)可以選多門課(Course)
  • 每門課(Course)也可以有多位學生(Student)

這種情況就需要第三張「中間表」(Pivot Table)


資料表設計

  • students:學生
  • courses:課程
  • course_student:中間表,存放 student_idcourse_id
Schema::create('course_student', function (Blueprint $table) {
    $table->id();
    $table->foreignId('student_id')->constrained()->onDelete('cascade');
    $table->foreignId('course_id')->constrained()->onDelete('cascade');
    $table->timestamps();
});

Model 寫法

// Student.php
public function courses()
{
    return $this->belongsToMany(Course::class);
}

// Course.php
public function students()
{
    return $this->belongsToMany(Student::class);
}

如何運用??

// 學生選課
$student = Student::find(1);
$student->courses()->attach(2); // 選 ID=2 的課
$student->courses()->attach([3, 4]); // 選多門課

// 退選
$student->courses()->detach(3);

// 查詢學生的課程
$courses = $student->courses;

// 查詢課程的學生
$course = Course::find(2);
$students = $course->students;

💡 Pivot 欄位
如果中間表還有額外欄位(例如成績 grade),可以用:

$student->courses()->attach(2, ['grade' => 90]);

取出:

foreach ($student->courses as $course) {
    echo $course->pivot->grade;
}

HasManyThrough(透過關聯取得資料)

什麼是 HasManyThrough?

  • 一個國家(Country)有很多用戶(User)
  • 每個用戶(User)有很多文章(Post)
  • 我想直接從 國家 找到 所有文章HasManyThrough

資料表設計

  • countries:國家
  • users:有 country_id
  • posts:有 user_id

Model 寫法

// Country.php
public function posts()
{
    return $this->hasManyThrough(Post::class, User::class);
}

如何運用??

$country = Country::find(1);
$posts = $country->posts; // 直接拿到這個國家的所有文章

小提醒(常見錯誤)

  1. 多對多的中間表命名
    預設是兩個單數表名按字母排序,例如 course_student,不要自己亂改。

  2. HasManyThrough 的中間 Model
    要正確設定「目標 Model」和「中間 Model」,順序不能反。

  3. attach / detach / sync

    • attach() → 新增關聯
    • detach() → 移除關聯
    • sync() → 同步關聯(會刪掉不在陣列中的項目)

小結

  • Many-to-Many:需要一張中間表(Pivot Table)
  • HasManyThrough:透過中間 Model 直接取得遠端資料
  • Eloquent 幫我們省去大量 SQL,讓關聯查詢更直覺

上一篇
【Day11】Model 關聯(One-to-One、One-to-Many)
下一篇
【Day13】Laravel 驗證(Validation)
系列文
Laravel 30天速成筆記16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言