2015-02-11 1 views
5

http://laravel.com/docs/4.2/eloquent#dynamic-propertiesPiù chiamate alla proprietà dinamica Eloquent colpiscono il database più volte?

class Phone extends Eloquent { 

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

} 

$phone = Phone::find(1); 

Ora, se io poi fare qualcosa di simile:

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

Will Eloquente effettuare una chiamata di database per ogni volta che uso la proprietà dinamica ->user? O è abbastanza intelligente da mettere in cache l'utente alla prima chiamata?

+0

Un'iterazione effettuare una chiamata a '' Phone' e user'. Molteplici iterazioni devi caricarti. http://laravel.com/docs/5.0/eloquent#eager-loading – user2094178

+0

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

+3

Credo che il primo riferimento a '$ telefono-> utente' caricherà il modello 'User' completo di tutti gli attributi locali a quel modello. Supponendo che 'email',' name' e 'nickname' siano memorizzati in' User', questo comporterebbe solo due query del database (una per il telefono, un'altra per l'utente). Provalo: dopo queste istruzioni, esegui 'dd (\ DB :: getQueryLog())' per vedere le query esatte fatte. – bishop

risposta

5

Nell'esempio, l'attributo user sull'oggetto $phone sarà pigro caricato, ma verrà caricato solo una volta.

Tenere presente, inoltre, che una volta caricato l'oggetto, non riflette alcuna modifica alla tabella sottostante a meno che non si ricarichi manualmente la relazione utilizzando il metodo load.

Il codice seguente illustra l'esempio:

$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

Ciò significa che anche se ho utilizzato il caricamento ansioso per ottenere gli stessi dati, otterrei comunque due chiamate al database quando sto recuperando solo un oggetto. Riassumo perfettamente le mie domande su questo. Grazie. – thomthom

+2

@thomthom Sì, il caricamento ansioso creerà almeno due chiamate al database. Tuttavia, previene il problema n + 1. Se hai fatto '$ phones = Phone :: all();', e poi foreach attraverso tutti gli oggetti del telefono e visualizzato il nome utente, farebbe una query per ottenere tutti i telefoni, e quindi una query utente separata per ogni singolo loop iteration (n + 1). Tuttavia, se si caricano con ansia facendo '$ phones = Phone :: with ('user') -> get();', ed esegui lo stesso foreach, questo farà solo 2 chiamate database totali, una per i telefoni, e uno per tutti gli utenti correlati. – patricus