Laravel Eloquent 模型關聯速查表

Charlie_Jade發表於2018-08-17

file

一張 Laravel’s Eloquent ORM 5.5 的速查表

一對一關聯

展示細節:

在這個展示中,我們有 2 個模型(Owner 和 Car)及兩張表(owners 和 cars)。

商業邏輯:

一個使用者可以擁有一臺車。
一臺車可以有一個擁有者。

關聯圖:

file

關聯細節:

Cars 表必須儲存 Owner ID。

Eloquent 模型:

class Owner
{
    public function car()
    {
       return $this->hasOne(Car::class);
    }
}
class Car
{
    public function owner()
    {
        return $this->belongsTo(Owner::class);
    }
}

資料庫遷移:

Schema::create(`owners`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`cars`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
    $table->integer(`owner_id`)->unsigned()->index()->nullable();
    $table->foreign(`owner_id`)->references(`id`)->on(`owners`);
});

儲存紀錄:

// 在 Owner 及 Car 之間建立關聯
$owner->car()->save($car);
// 在 Car 及 Owner 之間建立關聯
$car->owner()->associate($owner)->save();

取得紀錄:

// 取得 Owner Car
$owner->car;
// 取得 Car Owner
$car->owner;

一對多關聯

示例細節:

在此示例中,我們有兩個模型:Thief (小偷) 和 Car (車),和兩張表:
thieves 和 cars 。

業務規則:

小偷可以偷走多輛車。
車只能被一個小偷偷走。

關係圖:

file

關係細節:

車輛表應該儲存小偷的 ID 。

Eloquent 模型:

class Thief
{
    public function cars()
    {
       return $this->hasMany(Car::class);
    }
}
class Car
{
    public function thief()
    {
        return $this->belongsTo(Thief::class);
    }
}

資料遷移:

Schema::create(`thieves`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`cars`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
    $table->integer(`thief_id`)->unsigned()->index()->nullable();
    $table->foreign(`thief_id`)->references(`id`)->on(`thieves`);
});

記錄儲存:

// 建立介於小偷與車之間的關聯。
$thief->cars()->saveMany([
   $car1, 
   $car2,
]);
// 或者在單一模型呼叫 save() 方法。
$thief->cars()->save($car);
// 建立介於 Car 和 Thief 的關聯。
$car->thief()->associate($thief)->save();

拉取記錄:

// 獲取小偷所偷的車
$thief->cars;
// 獲取偷盜某輛車的小偷
$car->thief;

多型一對多關係

演示細節:

在這個演示中,我們有三個模型(Man, Woman 和 Car),和三張表(man, women 和 cars)。

業務規則:

一個男人(買家)可以買很多汽車。
一個女人(買家)可以買很多汽車。
這個汽車可以被一個買家購買(男人或女人)。

關係圖:

file

關係詳情:

Car表應該儲存買家 ID 和買家型別。
“buyer” 是一組模型名稱 (男人 和 女人), 它不僅限於兩者,buyer 型別是模型的真實名稱 。

Eloquent 模型:

class Man
{
    public function cars()
    {
        return $this->morphMany(Car::class, `buyer`);
    }
}
class Woman
{
    public function cars()
    {
        return $this->morphMany(Car::class, `buyer`);
    }
}
class Car
{
    public function buyer()
    {
        return $this->morphTo();
    }
}

資料庫遷移:

Schema::create(`men`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`women`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`cars`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
    $table->integer(`buyer_id`)->unsigned()->index()->nullable();
    $table->string(`buyer_type`)->nullable();   
    // 或者使用 $table->morphs(‘buyer’); 代替 "buyer_id" 和 "buyer_type"
});

儲存記錄:

// 在買家 (男人 / 女人) 和汽車之間建立聯絡。
$man->cars()->saveMany([
   $car1, 
   $car2,
]);
$woman->cars()->saveMany([
   $car1, 
   $car2,
]);
// 或者為單個模型使用 save() 函式。
$man->cars()->save($car);
$woman->cars()->save($car);
//建立汽車與買家之間的關係 ( 男人/女人 )。
$car1->buyer()->associate($man)->save();
$car2->buyer()->associate($woman)->save();

檢索記錄:

// 獲取買家 (男人 / 女人)的汽車
$men->cars
$women->cars
// 獲取這輛車的買家 (男人 / 女人)
$car->buyer

多對多關聯

示例展示:

在這個示例中,我們有兩個模型(Driver 和 Car),和三張表
(drivers,名為 car_driver的中間關聯表).

業務規則:

一個司機可以駕駛很多輛車。
一輛車可以被很多個司機開。

關係圖:

檔案

關聯詳情:

關聯表”car_driver”應該儲存駕駛員ID和汽車ID。

關聯模型:

class Driver
{
    public function cars()
    {
       return $this->belongsToMany(Car::class);
    }
}
class Car
{
    public function drivers()
    {
        return $this->belongsToMany(Driver::class);
    }
}

資料庫遷移:

Schema::create(`drivers`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`cars`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`car_driver`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->integer(`car_id`)->unsigned()->index();
    $table->foreign(`car_id`)->references(`id`)->on(`cars`)->onDelete(`cascade`);
    $table->integer(`driver_id`)->unsigned()->index();
    $table->foreign(`driver_id`)->references(`id`)->on(`drivers`)->onDelete(`cascade`);
});

儲存記錄:

//建立Driver和Car之間的關聯。
$driver->cars()->attach([
   $car1->id,
   $car2->id,
]);
//或者使用sync()函式防止重複關聯。
$driver->cars()->sync([
   $car1->id,
   $car2->id,
]);
//建立Car和Driver之間的關聯。
$car->drivers()->attach([
   $driver1->id,
   $driver2->id,
]);
//或者使用sync()函式防止重複關聯。
$car->drivers()->sync([
   $driver1->id,
   $driver2->id,
]);

查詢記錄:

// Get Driver Car
$driver->cars
// Get Car Drivers
$car->drivers

多對多多型關聯

展示細節:

在這個展示中我們有三個模型(Valet、Owner 及 Car)和 4 張表(valets、owners、cars 及 drivers)。

商業邏輯:

一個代駕(司機)可以駕駛很多輛車
一個車主(司機)可以駕駛很多輛車
一臺車可以被很多個司機駕駛(代駕和 / 或車主)

關聯圖

file

關聯細節:

中間表「drivers」應該儲存駕駛人 ID、駕駛人型別及車輛 ID。
駕駛是一個模型集合的代稱(Valet 及 Owner),而且不限定兩個模型。駕駛人型別是模型的真正名稱。

Eloquent 模型:

class Valet
{
    public function cars()
    {
        return $this->morphToMany(Car::class, `driver`);
    }
}
class Owner
{
    public function cars()
    {
        return $this->morphToMany(Car::class, `driver`);
    }
}
class Car
{
    public function valets()
    {
        return $this->morphedByMany(Valet::class, `driver`);
    }

    public function owners()
    {
        return $this->morphedByMany(Owner::class, `driver`);
    }
}

資料庫遷移:

Schema::create(`valets`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`owners`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->string(`name`);
});
Schema::create(`drivers`, function (Blueprint $table) {
    $table->increments(`id`);
    $table->integer(`driver_id`)->unsigned()->index();
    $table->string(`driver_type`);
    // 或使用 $table->morphs(‘driver’) 來取代「driver_id」和「driver_type」
    $table->integer(`car_id`)->unsigned()->index();
    $table->foreign(`car_id`)->references(`id`)->on(`cars`)->onDelete(`cascade`);
});

儲存紀錄:

// 在 driver(Valet / Owner)和 Car 間建立關聯
$valet->cars()->saveMany([$car1, $car2]);
$owner->cars()->saveMany([$car1, $car2]);
// 或使用 save() 方法來儲存單一模型
$valet->cars()->save($car1);
$owner->cars()->save($car1);
// 在 Car 和 driver(Valet / Owner)間建立關聯
$car->valets()->attach([
    $valet1->id,
    $valet2->id,
]);
$car->owners()->attach([
    $owner1->id,
    $owner2->id,
]);
// 或是用 sync() 方法來避免重複關聯
$car->valets()->sync([
    $valet1->id,
    $valet2->id,
]);
$car->owners()->sync([
    $owner1->id,
    $owner2->id,
]);

取得紀錄:

// 取得 driver(Valet / Owner)的 Cars
$valet->cars
$owner->cars

// 取得 Car 的 drivers(Valet 及 Owner)
$car->owners
$car->valets

file

更多現代化 PHP 知識,請前往 Laravel / PHP 知識社群

相關文章