Laravel - Eloquente "Has", "With", "WhereHas" - Che cosa significano?


212

Ho trovato il concetto e il significato dietro questi metodi per essere un po 'confuso, è possibile per qualcuno spiegarmi qual è la differenza tra hased withè, nel contesto di un esempio (se possibile)?

Risposte:


558

Con

with()è per il caricamento desideroso . Ciò significa sostanzialmente che, lungo il modello principale, Laravel precaricherà le relazioni specificate. Ciò è particolarmente utile se si dispone di una raccolta di modelli e si desidera caricare una relazione per tutti loro. Perché con il caricamento desideroso si esegue solo una query DB aggiuntiva anziché una per ogni modello nella raccolta.

Esempio:

User > hasMany > Post

$users = User::with('posts')->get();
foreach($users as $user){
    $users->posts; // posts is already loaded and no additional DB query is run
}

ha

has()è filtrare il modello selezionato in base a una relazione. Quindi agisce in modo molto simile a una normale condizione WHERE. Se lo usi, has('relation')significa che vuoi solo ottenere i modelli che hanno almeno un modello correlato in questa relazione.

Esempio:

User > hasMany > Post

$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection

WhereHas

whereHas()funziona sostanzialmente come, has()ma consente di specificare filtri aggiuntivi per il controllo del modello correlato.

Esempio:

User > hasMany > Post

$users = User::whereHas('posts', function($q){
    $q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned

101
+1, risposta molto utile! Si noti inoltre che mentre with('relation')includerà i dati del relativo della tabella nella collezione restituita, has('relation')e whereHas('relation')sarà non includono i dati della relativa tabella. Quindi potrebbe essere necessario chiamare sia with('relation')così come has()o whereHas().
Soulriser,

1
Saluta risposta, come accedere al modello principale dal modello di relazione, ad esempio qui come cercare il modello di post in base agli attributi del modello utente
hussainfrotan,

@BhojendraNepal Sfortunatamente non sembra esserci molto nei documenti ... Questo è tutto ciò che ho trovato (è qualche paragrafo in basso)
lukasgeiter

@hussainfrotan allo stesso modo, utilizzare whereHasla relazione utente durante la query di posta.
Michael Tsang,

Curioso, nella documentazione di Laravel: laravel.com/docs/5.8/eloquent-relationships , quando whereHaslo si utilizza utilizza use Illuminate\Database\Eloquent\Builder;quindi function(Builder $query). La maggior parte degli esempi che ho visto, dot usa il Builder, basta passare nella $ query, qual è la strada giusta?
Guntar,

8

Il documento ha già spiegato l'utilizzo. Quindi sto usando SQL per spiegare questi metodi

Esempio:


Supponendo che ce ne siano Order (orders)molti OrderItem (order_items).

E hai già costruito il rapporto tra loro.

// App\Models\Order:
public function orderItems() {
    return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}

Questi tre metodi sono tutti basati su una relazione .

Con


Risultato: with() restituisce l'oggetto modello e i relativi risultati.

Vantaggio: è il caricamento impaziente che può prevenire il problema N + 1 .

Quando si utilizza il seguente generatore di eloquenti:

Order::with('orderItems')->get();

Laravel cambia questo codice in solo due SQL :

// get all orders:
SELECT * FROM orders; 

// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);

E poi laravel unisce i risultati del secondo SQL in modo diverso dai risultati del primo SQL con chiave esterna . Alla fine restituisci i risultati della raccolta.

Quindi se hai selezionato le colonne senza la chiave_estra in chiusura, il risultato della relazione sarà vuoto:

Order::with(['orderItems' => function($query) { 
           // $query->sum('quantity');
           $query->select('quantity'); // without `order_id`
       }
])->get();

#=> result:
[{  id: 1,
    code: '00001',
    orderItems: [],    // <== is empty
  },{
    id: 2,
    code: '00002',
    orderItems: [],    // <== is empty
  }...
}]

ha


Hasrestituirà l'oggetto del modello che la sua relazione non è vuota .

Order::has('orderItems')->get();

Laravel cambia questo codice in un SQL :

select * from `orders` where exists (
    select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)

whereHas


whereHase orWhereHasmetodi per porre wherecondizioni alle tue hasdomande. Questi metodi consentono di aggiungere vincoli personalizzati a un vincolo di relazione .

Order::whereHas('orderItems', function($query) {
   $query->where('status', 1);
})->get();

Laravel cambia questo codice in un SQL :

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.