Laravel Eloquent中的 懶載入VS即時載入

如來神掌發表於2019-02-16

Laravel中的Eloquent(ORM)的工作方式很令人驚訝,並提供訪問資料庫的非常簡單的方法。在本文中,我們將瞭解Laravel Eloquent中的懶載入和即時載入以及它如何在後臺執行。

Eloquent 中的關係

第一步我們需要定義模型之間的關係的。在這個例子中,我將使用兩個模型,housecity。房子屬於一個城市,城市有很多房屋。讓我們看看模型 House 的關係:

class House extends Model
{
    protected $fillable = [
        `title`, `description`, `price`
    ];

    public function city() {
        return $this->belongsTo(`AppCity`);
    }
}

注意:對於多對一的關係(房子屬於一個城市),函式名稱是單數。 [public function city()]

class City extends Model
{
    protected $fillable = [
        `name`, `code`
    ];

    public function houses() {
        return $this->hasMany(`AppHouse`);
    }
}

注意:對於一對多關係(城市有很多房屋),函式名稱是複數。 [public function houses()]

懶載入

$houses = House::all();

預設情況下,在Eloquent中訪問資料是“懶載入”,在上面的程式碼中,我們獲取了所有資料在內部表中,實際執行的SQL查詢是:

select * from `houses`

在這一步中,關係表(城市)中的資料還沒有被獲取,如果我們想訪問關係表中的資料,我們可以像這樣訪問:

foreach ($houses as $house) {
    echo $house->city->name; // 這就是懶載入
}

實際執行的SQL查詢是

select * from `cities` where `cities`.`id` = ? limit 1
select * from `cities` where `cities`.`id` = ? limit 1
select * from `cities` where `cities`.`id` = ? limit 1
...

該過程將迴圈房屋內的所有記錄,併為每個迴圈執行1次查詢以獲取城市資料,例如我們有20個房屋記錄,查詢獲取關係表中的資料將執行20次+1原始查詢獲取 房屋資料,查詢“延遲載入”的時間是N + 1。

即時載入

有時在應用程式中使用即時載入非常有用,例如,你正在使用Ajax呼叫資料,在這種情況下,我們必須使用預載入來準備在關係表中包含資料的所有資料,然後再將結果返回給Ajax。 要使用即時載入,只需在獲取資料時使用 with 方法。

$houses = House::with(`city`)->get();

現在所有的房屋資料和在關係表中的資料都同時載入出來了,查詢的SQL語句的是

select * from houses
select * from cities where id in (1, 2, 3, 4, 5, ...)

使用即時載入時僅執行2個查詢。 正如你可以看到上面的查詢,一個查詢是在房屋表中獲取所有資料,另一個查詢是獲取城市表中的所有資料,使用IN操作將ID與房屋表中的city_id匹配。

懶載入 和 即時載入

在某些情況下,這對於即時動態載入非常有用,我們可以決定是否需要載入關係表中的資料。

$houses = House::all();

if($isLoad) {
    $houses->load(`city`); // 對應 house model中的 city 方法
}

我們可以使用 load 方法在特定條件下載入關係表中的資料。

這一點非常有用,實際中大家可以多試試。

總結

現在你理解了這個過程,希望它能幫助你理解懶載入和即時載入的用法和基本原理。

更多PHP知識,可以前往PHPCasts

相關文章