Laravel 模型關聯基礎教程

文章轉發自專業的Laravel開發者社區,原始連接: https://learnku.com/laravel/t...

在 Laravel 中定義模型關聯是每一個 Laravel 開發者可能已經作過不止一次的事情。可是在試圖實現關聯時可能會遇到各類問題。由於 Laravel 有各類各樣的關聯,你應該選擇哪個?當涉及到查詢模型時,咱們如何充分利用模型關聯的功能?php

Laravel 的模型關聯可能會讓人糊塗。若是你不徹底理解 Laravel 的關聯在這一點上是如何工做的,別擔憂,讀完這篇文章後,你會更好地理解它。laravel

咱們應該使用哪一個模型關聯?

要回答這個問題,首先你要知道有哪些可用的選項。Laravel 有 3 種不一樣的關聯類型。數據庫

  • 一對一
  • 一對多
  • 多對多

咱們將逐個探討不一樣的關聯類型並解釋一下應該何時使用它們。this

一對一

一對一關聯是目前存在的最基本的關聯。這種關聯意味着 A 模型只能連接到 B 模型,相反也是如此。舉個例子,一個 User 模型和一個 Passport 模型會成爲一對一的關聯。一個用戶只能擁有一張通行證,一樣,一張通行證也只屬於一個用戶。spa

讓咱們看看如何在代碼中定義這種關聯。code

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    public function passport() {
        return $this->hasOne(App\Passport::class);
    }
}

User 模型中咱們建立了一個 passport 方法。咱們經過 hasOne 方法告訴 Laravel User 模型有一個 Passportblog

注意:
全部用於定義關聯的方法都有可選的額外參數,你能夠在這些參數中定義本地鍵和外鍵。默認狀況下,Laravel會假設你在用戶模型中定義了 passport_id ,由於你試圖建立與 passport 模型的關聯。建立遷移文件時也請注意這一點!

Passport 模型中,咱們須要定義逆向的關聯。咱們要讓 Passport 模型知道它屬於 User 模型。咱們可使用 belongsTo 方法來實現這一點。開發

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Passport extends Model
{
    public function user() {
        return $this->belongsTo(App\User::class);
    }
}

一對多

你能夠在 Laravel 中定義的下一個關聯是一對多關聯。 這種類型的關聯意味着一個類型A的模型能夠連接到多個類型B的模型。可是類型B的模型只屬於一個類型A的模型。rem

例如,User 模型和 Invoice 模型之間的關聯是一對多關聯。 用戶能夠擁有多個帳單,但帳單僅屬於一個用戶。get

在代碼中是這樣寫的:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    public function invoices() {
        return $this->hasMany(App\Invoice::class);
    }
}

它看起來就像咱們以前用於定義一對一關聯的代碼,對吧?

咱們如今要作的就是讓 Invoice 模型知道它屬於 User 模型。 讓咱們定義一對多關聯的反向對應關聯吧。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
    public function user() {
        return $this->belongsTo(App\User::class);
    }
}

多對多

最後要定義的關聯是多對多關聯。 這種類型的關聯意味着類型A的一個模型能夠連接到類型B的多個模型,反之亦然。

例如,Invoice  模型和 Product  模型之間的關聯將是多對多關聯。 帳單能夠包含多個產品,而產品能夠屬於多個帳單。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
    public function products() {
        return $this->belongsToMany(App\Product::class);
    }
}

你能夠像這樣定義這種關聯的反向關係:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
    public function invoices() {
        return $this->belongsToMany(App\Invoice::class);
    }
}

多對多關聯實現起來稍微困難一些,由於它們須要數據庫中的中間表。 你能夠經過建立遷移文件在 Laravel 中建立此中間表。

遠程關聯

遠程一對一

has one through 關聯經過單箇中間關聯模型實現。 若是每一個供應商都有一個用戶,而且每一個用戶與一個用戶歷史記錄相關聯,那麼供應商能夠經過用戶訪問用戶的歷史記錄。

這就是定義這種關聯所需的數據庫表:

suppliers:
- idproducts:
- id
- supplier_idproduct_history:
- id
- product_id

即便 product_history 表不包含 supplier_id 列,供應商也能夠經過使用 「has one through」 關係訪問 product_history 記錄。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Supplier extends Model
{
    public function productHistory() {
        return $this->hasOneThrough(App\History::class, App\Product::class);
    }
}

傳遞給 hasOneThrough 方法的第一個參數是但願訪問模型的名稱。 第二個參數是中間模型的名稱。

遠程一對多

「has many through」 關聯至關於 「has one through」 關聯,只是對於多個記錄的。 讓咱們使用前面的示例,但咱們改變一件事:產品如今能夠有多個歷史條目而不是一個。 數據庫表保持不變。

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Supplier extends Model
{
    public function productHistory() {
        return $this->hasManyThrough(App\History::class, App\Product::class);
    }
}

這樣,供應商模型能夠訪問產品的歷史記錄條目。

查詢關聯

查詢一個關聯很是簡單。由於咱們定義了 Passport 的一對一關聯和 Invoice 的一對多關聯,因此咱們能夠在 User 模型中使用它們。在 User 模型的每一個實例上,咱們均可以獲得對應的 Passport 和 Invoice。

<?php
$user = \App\User::find(1);

// 查詢 passport 關聯
$user->passport->expiration_date;

// 查詢 invoice 關聯
foreach($user->invoices as $invoice) {
    $invoice->total_amount;
}

也能夠查詢關聯的反向關聯。 若是您有帳單,則能夠得到該帳單的用戶。

<?php
$invoice = \App\Invoice::find(1);
// Get the user
$invoice->user->first_name;

查詢多對多關聯的工做方式與其餘關聯徹底相同。 此外,多對多關聯有一個pivot 屬性。 此屬性表示中間表,能夠像任何其餘模型同樣使用。

舉個例子,假設鏈接的表有 created_at 字段,咱們就可使用 pivot 來獲取 created_at 字段。

<?php
$invoice = \App\Invoice::find(1);
// 獲取  product 的 `created_at` 字段
foreach($invoice->products as $product) {
    $product->pivot->created_at;
}

查詢 has one throughhas many through 的工做方式與其餘關聯徹底相同。

添加約束

能夠在查詢時向關係添加約束。看看下面的示例:

<?php
$user->passport()->where('active', 1)->orderBy('expiration_date');

檢查關聯是否存在

有時候你但願檢查模型中是否有添加某些關聯, Laravel有一些方法能夠幫助你用來檢查:

<?php
// 找到擁有護照的全部用戶
$users = App\User::has('passport')->get();

// 找到沒擁有護照的全部用戶
$users = App\User::doesntHave('passport')->get();

// 找到擁有 5 個及以上產品的發票
$invoices = App\Invoice::has('products', '>=', 5)->get();

但願這篇文章能讓你對Laravel的模型關聯有更好的理解。謝謝你的閱讀!

相關文章
相關標籤/搜索