簡體   English   中英

Laravel 5:默認情況下,雄辯的渴望加載嗎?

[英]Laravel 5: Does Eloquent eager load by default?

我有這個結構:

學校-> hasMany->班級

所以當我通過artisan tinker嘗試以下代碼時

App\School::with('schoolclasses')->find(2283)->schoolclasses;

我可以順利上課。

但是當我嘗試不使用with時,我仍然會得到相同的結果而不會出現問題:

App\School::find(2283)->schoolclasses;

Eloquent默認加載Eloquent嗎? 如果是這樣,如何禁用它?

不,Laravel默認不急於加載。 讓我們逐步進行此操作。 讓我們忽略->schoolclasses; 一會兒。

App\School::with('schoolclasses')->find(2283);

這將查詢數據庫兩次。 首先,它將獲得主鍵2283的School 。然后,它將立即查詢數據庫並獲取所有相關的schoolclasses

App\School::find(2283);

這將只查詢數據庫一次。 它只會得到School 到目前為止,尚未完成任何急切的加載。 如果調試並跟蹤數據庫查詢,您將看到它只會查詢數據庫一次,而急於加載的數據庫將查詢兩次。

當您嘗試訪問schoolclasses->schoolclasses; ,一切實際上都有效。 那為什么得到相同的結果呢? 這有點騙人,但是不一樣。 當您嘗試訪問schoolclasses ,Laravel將檢查它是否已經被加載。 如果是這樣,它將返回schoolclasses的集合。 沒有查詢完成。 它只是立即返回它們。 但是,如果您不急於加載它們,Laravel將立即查詢數據庫並獲取schoolclasses 最終,對於此特定示例,您將獲得相同的結果,但是查詢數據庫時卻有所不同。

但是,這實際上是渴望加載的主要好處的不良示例。

渴望加載的主要好處是減輕了N + 1查詢問題。 假設您想獲得5所學校及其所有班級。 如果不急於加載,這是您要執行的操作:

$schools = School::take(5)->get();

foreach ($schools as $school)
{
    $schoolclasses = $school->schoolclasses;
}

對於這樣一個簡單的任務,總共有6個查詢。 我在下面添加了注釋,以了解查詢來自何處:

$schools = School::take(5)->get(); // First query

foreach ($schools as $school)
{
    // For each school, you are querying the database again to get its related classes.
    // 5 schools = 5 more queries
    $schoolclasses = $school->schoolclasses;
}

但是,如果您渴望加載所有內容,則只有兩個查詢:

// Two queries here that fetches everything
$schools = School::with('schoolclasses')->take(5)->get();

foreach ($schools as $school)
{
    // No more queries are done to get the classes because
    // they have already been eager loaded
    $schoolclasses = $school->schoolclasses;
}

您兩次寫相同。 第一個請求到達學校,其課程如下:

學校:

班級班級

然后,您僅獲得課程。

第二個直接獲取這些類。 結果是相同的,因為您要的是相同的記錄。

如果您不想獲得急切加載的結果,那就不要查詢它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM