2015-02-11 66 views
5

http://laravel.com/docs/4.2/eloquent#dynamic-properties多次調用Eloquent動態屬性是否會多次訪問數據庫?

class Phone extends Eloquent { 

    public function user() 
    { 
     return $this->belongsTo('User'); 
    } 

} 

$phone = Phone::find(1); 

現在,如果我那麼做這樣的事情:

echo $phone->user->email; 
echo $phone->user->name; 
echo $phone->user->nickname; 

威爾洋洋灑灑做一個數據庫調用的每一次我使用->user動態屬性?或者這足夠聰明,可以在第一次通話時緩存用戶?

+0

一次迭代將對'Phone'和'User'通話。多次迭代你必須急切加載。 http://laravel.com/docs/5.0/eloquent#eager-loading – user2094178 2015-02-11 04:23:48

+0

http://laravel.com/docs/4.2/eloquent#eager-loading – user2094178 2015-02-11 04:24:35

+3

我相信對'$ phone-> user'的第一個引用將加載具有該模型本地所有屬性的「用戶」模型。假定'email','name'和'nickname'存儲在'User'中,那麼這將導致只有兩個數據庫查詢(一個用於電話,另一個用於用戶)。試試看:在這些語句之後,運行dd(\ DB :: getQueryLog())來查看所做的確切查詢。 – bishop 2015-02-11 04:27:26

回答

5

在您的示例中,$phone對象上的user屬性將被延遲加載,但只會加載一次。

請記住,一旦加載對象,它不會反映對基礎表的任何更改,除非使用load方法手動重新加載關係。

下面的代碼說明的例子:

$phone = Phone::find(1); 

// first use of user attribute triggers lazy load 
echo $phone->user->email; 

// get that user outta here. 
User::destroy($phone->user->id); 

// echoes the name just fine, even though the record doesn't exist anymore 
echo $phone->user->name; 

// manually reload the relationship 
$phone->load('user'); 

// now will show null, since the user was deleted and the relationship was reloaded 
var_export($phone->user); 
+0

這意味着,即使我使用預先加載來獲取相同的數據,當我僅獲取一個對象時仍然會得到兩個數據庫調用。完美總結我對此的疑問。謝謝。 – thomthom 2015-02-11 05:17:13

+2

@thomthom是的,急切的加載將創建至少兩個數據庫調用。但是,它可以防止n + 1問題。如果您執行了'$ phones = Phone :: all();',然後遍歷所有電話對象並顯示用戶名,則會執行一個查詢來獲取所有電話,然後爲每個單獨的用戶查詢循環迭代(n + 1)。但是,如果您通過執行'$ phones = Phone :: with('user') - > get();'來執行加載操作,並且運行相同的foreach,則只會完成2個數據庫調用,一個用於電話,一個用於所有相關用戶。 – patricus 2015-02-11 05:21:53