2025年12月3日 星期三

Laravel 12 Eloquent 關聯完整指南:從基礎到進階的全方位教學

相關系列文章:
01.在 windows 10 安裝 laravel 12 studentManagement環境與設定
02.laravel 12 route 路由
03.laravel 12 Blade Templates 網頁模版
04.laravel 12 Controller 控制器 
05.Laravel 12 Migration 遷移-資料庫版本控制
06.Laravel 12 Model 資料庫中的資料表,並提供與資料庫互動的介面
07.laravel 資料庫資料填充工廠入門
08.laravel 12 Eloquent ORM-Query Builder
09.laravel 12 Eloquent ORM-Eloquent ORM
10.Laravel 12:Eloquent 必學技巧一次掌握(Scopes、Soft Deletes、CRUD)
11.Laravel 12 表單驗證教學
12.Laravel 12 圖片上傳與刪除記錄及文件
13.Laravel 12 Eloquent 關聯完整指南:從基礎到進階的全方位教學

在這章節,總共分成6大部分:
1.Laravel 12 一對一關聯教學|Eloquent 關聯完整解說
2.Laravel 12 一對多關聯教學|掌握 Eloquent 關聯
3.Laravel 12 多對多關聯教學|Eloquent Pivot 樞紐表詳解
4.Laravel 12 Has One Through 關聯|Eloquent 間接一對一關聯
5.Laravel 12 Has Many Through 關聯|透過 Eloquent 取得間接的相關資料
6.Laravel 12 多型關聯解說|一個模型對應多個資料表
其細節討論如下:

1.Laravel 12 一對一關聯教學|Eloquent 關聯完整解說
以下示範 User 與 Profile 的一對一關聯:
(1)利用Chatgpt 來建立範例
a. 請給我一個 laravel 12 範例,關於Laravel 12 One to One Relationship Tutorial | Eloquent Relationship Explained
b.那如何在上述範例中,建立10筆資料。請詳加說明

(2)建立OneToOne專案語法:composer create-project laravel/laravel OneToOne
此時已內建create_users_table

(3)建立 profiles table
指令:php artisan make:migration create_profiles_table
編輯內容:

$table->id();
$table->unsignedBigInteger('user_id');
$table->string('bio')->nullable();
$table->string('phone')->nullable();
$table->timestamps();

// One-To-One FK
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

如下圖:

(4)建立Model
建立Profile 指令:php artisan make:model Profile
如下圖:
User Model (app/Models/User.php)
    public function profile() {
        return $this->hasOne(Profile::class);
    }

如下圖:

 Profile Model (app/Models/Profile.php)

    protected $fillable = [
        'user_id','bio','phone'
    ];
    public function user() {
        return $this->belongsTo(User::class);
    }

如下圖:

(5)用 Route + Controller +Blade 顯示範例
routes/web.php
Route::get('/user/{id}',function($id){
    $user = User::with('profile')->findOrFail($id);
    return view('user',compact('user'));
});

Route::get('/profile/{id}',function($id){
    $profile = Profile::with('user')->findOrFail($id);
    return view('profile',compact('profile'));
});

如下圖:

resources/views/user.blade.php

<h1>{{ $user->profile->id }}</h1>
<p>{{ $user->profile->bio }}</p>
<p>{{ $user->profile->phone }}</p>

如下圖:

resources/views/profile.blade.php

<h1>{{ $profile->user->id }}</h1>
<p>{{ $profile->user->name }}</p>
<p>{{ $profile->user->email }}</p>

如下圖:

(6)用 Seeder 建立 10 筆資料
指令:php artisan make:seeder UserSeeder

        for ($i = 1; $i <= 10; $i++) {
            $user = User::create([
                'name'  => 'User ' . $i,
                'email' => 'user' . $i . '@example.com',
                'password' => bcrypt('admin'.$i),
            ]);
            $user->profile()->create([
                'bio'   => 'This is bio for user ' . $i,
                'phone' => '09000000' . $i,
            ]);
        }

如下圖:

執行seeder
指令:php artisan db:seed --class=UserSeeder
如下圖:
此時,http://127.0.0.1:8080/phpmyadmin/ 可看到
127.0.0.1:8000/profile/1 與 127.0.0.1:8000/user/1 可看到

2.Laravel 12 一對多關聯教學|掌握 Eloquent 關聯
User(使用者)→ Post(文章) 範例說明,一個 User 可以有多篇 Post。
一個 User 有多篇 Post;一篇 Post 屬於某個 User
(1)利用Chatgpt 來建立範例
a.請給我一個 laravel 12 範例,關於Laravel 12 一對多關聯教學|掌握 Eloquent 關聯。
b.那如何在上述範例中,建立10筆資料。請詳加說明。
(2)繼續利用原先的OneToOne 的專案,users table 已經完成。
接下來,建立posts table 語法:php artisan make:migration create_posts_table
如下圖:

編輯內容:

            $table->id();
            $table->unsignedBigInteger('user_id');//外鍵
            $table->string('title');
            $table->text('content');
            $table->timestamps();

            $table->foreign('user_id')
                  ->references('id')
                  ->on('users')
                  ->onDelete('cascade');  

如下圖:
(3)建立 Models 與 關聯
a.建立Post Model指令:php artisan make:model Post
Post Model — 一篇 Post 屬於 User
app/Models/Post.php 
    protected $fillable = [
        'user_id','title','content'
    ];
    public function user() {
        return $this->belongsTo(User::class);
    }

如下圖:
b.User Model — 一個 User 有多個 Post
app/Models/User.php 
    public function posts() {
        return $this->hasMany(Post::class);
    }
如下圖:


(4)用 Route + Controller +Blade 顯示示範
routes/web.php
Route::get('/posts/{id}',function($id){
    $user = User::with('posts')->findOrFail($id);
    return view('posts',compact('user'));
});
如下圖:

resources/views/posts.blade.php
<h1>{{ $user->name }}</h1>

<h2>Posts</h2>
<ul>
@foreach ($user->posts as $post)
    <li>{{ $post->title }}</li>
@endforeach
</ul>
如下圖:

(5) 清除原先的users table 與 profiles table 資料 並重新建立
users table、profiles table 與 posts table 資料
指令:php artisan migrate:reset 與 php artisan migrate
a.建立 10 筆 User +10 筆 Profile + 多筆 Post(一對多示範)
database/seeders/UserSeeder.php
            // 每個user 建立3篇文章
            for ($j = 1;$j <= 3; $j++) {
                $user->posts()->create([
                    'title' => "User $i - Post $j",
                    'content' => "Content for post $j of User $i.",
                ]);
            }

如下圖:

b.執行seeder
指令:php artisan db:seed --class=UserSeeder
此時,http://127.0.0.1:8080/phpmyadmin/ 可看到

127.0.0.1:8000/posts/1 


3.Laravel 12 多對多關聯教學|Eloquent Pivot 樞紐表詳解

User ↔ Role 範例
一個 User 可以有多個 Role;一個 Role 可以屬於多個 User
(1)利用Chatgpt 來建立範例
a.請給我一個 laravel 12 範例,關於Laravel 12 多對多關聯教學|Eloquent Pivot 樞紐表詳解
b.那如何在上述範例中,建立10筆資料。請詳加說明。
(2)繼續利用原先的OneToOne 的專案,users table 已經完成。
接下來,建立roles table 語法:php artisan make:migration create_roles_table
編輯其內容:
          $table->id();
            $table->string('name');
            $table->timestamps();
如下圖:

(3)建立 pivot:role_user 樞紐表
Laravel 多對多慣例使用 role_user(字母順序)
指令:php artisan make:migration create_role_user_table
編輯其內容:
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('role_id');
// 樞紐表額外欄位(可加可不加)
$table->boolean('is_active')->default(true);
// pivot 也可以有 timestamps
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
如下圖:

(4)Model 設定(belongsToMany)
a.User Model
app/Models/User.php
    public function roles() {
        return $this->belongsToMany(Role::class)
                    ->with(['is_active'])  // Pivot 額外欄位
                    ->withTimestamps();    // Pivot timestamps
    }
如下圖:

b.Role Model
app/Models/Role.php
指令:php artisan make:model Role
編輯其內容:
    protected $fillable = ['name'];
    public function users() {
        return $this->belongsToMany(User::class)
                    ->withPivot(['is_active'])
                    ->withTimestamps();
    }
如下圖:

(5)Route+Controller 範例
a.Route
routes/web.php
編輯內容:
Route::get('/assign-role',[RoleController::class,'assignRole']);
如下圖:
b.Controller
指令:php artisan make:controller RoleController
app/Http/Controllers/RoleController.php
    public function assignRole() {
        $user = User::find(1);
        $user->roles()->attach([
            1 => ['is_active' => true],
            2 => ['is_active' => false],
        ]);
        return "Roles assigned!";
    }
如下圖:

(6)清除原先的users table、profiles table 與 posts table 資料
指令:php artisan migrate:reset 與 php artisan migrate
a.Seeder 建立 10 個 User + 3 個 Role + 關聯
database/seeders/DatabaseSeeder.php

        //建立角色
        $admin = Role::create((['name' => 'Admin']));
        $editor = Role::create(['name' => 'Editor']);
        $viewer = Role::create(['name' => 'Viewer']);

        //建立10 個 user
        for ($i = 1;$i <= 10;$i++) {
            $user = User::create([
                'name' => "User $i",
                'email' => "User$i@gmail.com",
                'password' => bcrypt('User'.$i),
            ]);

        // 隨機給 user 賦予角色
            $user->roles()->attach([
                $admin->id => ['is_active' => rand(0,1)],
                $editor->id => ['is_active' => rand(0,1)],
            ]);
        }

如下圖:

b.執行,指令為 php artisan db:seed
(7) 在http://127.0.0.1:8080/phpmyadmin/ 可看到

4.Laravel 12 Has One Through 關聯|Eloquent 間接一對一關聯

透過中介 Model,間接取得另一個 Model 的單一資料。
Country → User → Post
一個國家(Country)有很多使用者(Users)
一個使用者(User)有一篇主要文章(Post)
我們希望:
Country 可以直接取得它底下的某個 User 的 Post(間接一對一)
如圖:
因此,使用 hasOneThrough()。
(1)利用Chatgpt 來建立範例
a.請給我一個 Laravel 12 範例,關於Has One Through 關聯|Eloquent 間接一對一關聯詳解
b.那如何在上述範例中,建立10筆資料。請詳加說明。
(2)
建立OneToOne專案語法:composer create-project laravel/laravel OneToOne
(3)建立資料表結構(migrations)
a.此時已內建create_users_table,編輯其內容:
$table->unsignedBigInteger('country_id');


 $table->foreign('country_id')->references('id')->on('countries')->onDelete('cascade');

如下圖:


b.建立create_countries_table,指令:php artisan make:migration create_countries_table,編輯其內容:

            $table->string('name');

如下圖:

c.建立create_posts_table,指令:php artisan make:migration create_posts_table,編輯其內容:

            $table->unsignedBigInteger('user_id');


            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

如下圖:
(4)Model 設定(hasOneThrough)
a.建立 Country Model,指令:php artisan make:model Country,編輯內容如下:
    public function post() {
        return $this->hasOneThrough(
            Post::class,  //間接要取得的目標 Model
            User::class,  //中介 Model
            'country_id',//users 表的外鍵(指向 countries)
            'user_id',   //posts 表的外鍵(指向users)
            'id',        //countries 的本地鍵
            'id'   //users 的本地鍵
        );
    }
如下圖:


b.已有 User Model,不需要建立,編輯內容如下:
    public function country() {
        return $this->belongsTo(Country::class);
    }
    public function post() {
        return $this->hasOne(Post::class);
    }

如下圖:

c.建立 Post Model,指令:php artisan make:model Post,編輯內容如下:
    public function user() {
        return $this->belongsTo(User::class);
    }
如下圖:
(5)建立Seeder資料(建立 10 個 Country,其下自動建立 User + Post)
a.指令:php artisan make:seeder CountrySeeder,編輯如下:
        // 建立 10 個國家
        Country::factory(10)->create()->each(function ($country) {
            // 每個國家建立 1 個 User
            $user = User::factory()->create([
                'country_id' => $country->id
            ]);
            // 該 user 建立 1 篇主要文章
            Post::factory()->create([
                'user_id' => $user->id
            ]);
        });
如下圖:
b.執行seeder
指令:php artisan db:seed --class=CountrySeeder



5.Laravel 12 Has Many Through 關聯|透過 Eloquent 取得間接的相關資料


6.Laravel 12 多型關聯解說|一個模型對應多個資料表












資料來源: 
1.Laravel 12 Eloquent Relationships Introduction | One to One, One to Many, Many to Many
2.Laravel 12 One to One Relationship Tutorial | Eloquent Relationship Explained
3.Laravel 12 One to Many Relationship Tutorial | Master Eloquent Relationships
4.Laravel 12 Many to Many Relationship Tutorial | Eloquent Pivot Table Explained







Laravel 12 Eloquent 關聯完整指南:從基礎到進階的全方位教學

相關系列文章: 01. 在 windows 10 安裝 laravel 12 studentManagement環境與設定 02. laravel 12 route 路由 03. laravel 12 Blade Templates 網頁模版 04. laravel 12 Con...