2015-02-11 17 views
5

http://laravel.com/docs/4.2/eloquent#dynamic-propertiesCzy wielokrotne wywołania do Wymownej właściwości dynamicznej trafią do bazy danych wiele razy?

class Phone extends Eloquent { 

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

} 

$phone = Phone::find(1); 

Teraz, gdybym wtedy coś takiego:

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

Will Eloquent nawiązać połączenie z bazą danych za każdym razem używam własności dynamiczne na ->user? Czy jest to wystarczająco inteligentne, aby buforować użytkownika podczas pierwszego połączenia?

+0

Jedna iteracja będzie zatelefonować do 'Phone' i' użytkownik portu. Wielokrotne iteracje trzeba bardzo szybko załadować. http://laravel.com/docs/5.0/eloquent#eager-loading – user2094178

+0

http://laravel.com/docs/4.2/eloquent#eager-loading – user2094178

+3

Wierzę, że pierwsze odniesienie do '$ phone-> user' załaduje model 'User' kompletny ze wszystkimi atrybutami lokalnymi dla tego modelu. Zakładając, że 'email',' name' i 'nickname' są przechowywane w' User', to spowoduje to tylko dwa zapytania do bazy danych (jeden dla telefonu, drugi dla użytkownika). Wypróbuj: po tych instrukcjach uruchom 'dd (\ DB :: getQueryLog())', aby zobaczyć dokładnie wykonane zapytania. – bishop

Odpowiedz

5

W twoim przykładzie atrybut user na obiekcie $phone zostanie załadowany w trybie leniwym, ale zostanie załadowany tylko raz.

Należy również pamiętać, że po załadowaniu obiektu nie odzwierciedla on żadnych zmian w tabeli podstawowej, chyba że ręcznie przeładowano relację za pomocą metody load.

Poniższy kod ilustruje przykład:

$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

Oznacza to, że nawet jeśli korzystałem z szybkiego ładowania, aby uzyskać te same dane, nadal otrzymywałbym dwie wywołania bazy danych, gdy pobieram tylko jeden obiekt. Doskonale podsumowuję moje pytania, które miałem na ten temat. Dziękuję Ci. – thomthom

+2

@thomthom Tak, chętne ładowanie utworzy co najmniej dwie wywołania bazy danych. Zapobiega to jednak problemowi n + 1. Jeśli zrobiłeś '$ phone = Phone :: all();', a następnie przejdziesz przez wszystkie obiekty telefonu i wyświetli nazwę użytkownika, wykona to jedno zapytanie, aby uzyskać wszystkie telefony, a następnie osobne zapytanie użytkownika dla każdego iteracja pętli (n + 1). Jeśli jednak chcesz się ładować, wykonaj '$ phones = Phone :: with ('user') -> get();' i uruchom te same foreach, które wykonają tylko 2 połączenia z bazą danych, jedną dla telefonów i jeden dla wszystkich powiązanych użytkowników. – patricus