Laravel - Eloquent "Hat", "Mit", "Wo hat" - Was bedeuten sie?

210

Ich habe das Konzept und die Bedeutung dieser Methoden als etwas verwirrend empfunden. Kann mir jemand erklären, was der Unterschied zwischen hasund withim Kontext eines Beispiels ist (wenn möglich)?

lukasgeiter
quelle

Antworten:

553

Mit

with()ist zum eifrigen Laden . Das bedeutet im Grunde, dass Laravel entlang des Hauptmodells die von Ihnen angegebenen Beziehungen vorlädt. Dies ist besonders hilfreich, wenn Sie über eine Sammlung von Modellen verfügen und für alle eine Beziehung laden möchten. Denn beim eifrigen Laden führen Sie nur eine zusätzliche DB-Abfrage anstelle einer für jedes Modell in der Sammlung aus.

Beispiel:

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
}

Hat

has()besteht darin, das Auswahlmodell basierend auf einer Beziehung zu filtern. Es verhält sich also sehr ähnlich zu einem normalen WHERE-Zustand. Wenn Sie nur verwenden has('relation'), bedeutet dies, dass Sie nur die Modelle erhalten möchten, die mindestens ein verwandtes Modell in dieser Beziehung haben.

Beispiel:

User > hasMany > Post

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

Wo hat

whereHas()funktioniert im Grunde genauso wie has(), ermöglicht es Ihnen jedoch, zusätzliche Filter für das zu überprüfende zugehörige Modell anzugeben.

Beispiel:

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
lukasgeiter
quelle
101
+1, sehr hilfreiche Antwort! Beachten Sie auch , daß , während with('relation')die Maßgebliche Tabelle der Daten in der zurückgegebenen Sammlung gehört, has('relation')und whereHas('relation')wird nicht die Daten der verknüpften Tabelle. Möglicherweise müssen Sie sowohl with('relation')als auch has()oder anrufen whereHas().
Soulriser
1
Grüße Antwort, Wie man vom Beziehungsmodell auf das
übergeordnete
@ BhojendraNepal Leider scheint es nicht viel darüber in den Dokumenten zu geben ... Dies ist alles, was ich gefunden habe (es ist ein paar Absätze weiter unten)
lukasgeiter
@hussainfrotan auf die gleiche Weise, verwenden Sie whereHasauf Benutzerbeziehung, wenn Sie Beitrag abfragen.
Michael Tsang
Neugierig, in der Laravel-Dokumentation: laravel.com/docs/5.8/eloquent-relationships , wenn whereHases verwendet wird, use Illuminate\Database\Eloquent\Builder;was dann mit ist function(Builder $query). Die meisten Beispiele, die ich gesehen habe, Punkt verwenden die Builder, übergeben Sie einfach die $ Abfrage, was ist der richtige Weg?
Guntar
8

Dokument hat die Verwendung bereits erklärt. Ich benutze SQL, um diese Methoden zu erklären

Beispiel:


Vorausgesetzt, es gibt Order (orders)viele OrderItem (order_items).

Und Sie haben bereits die Beziehung zwischen ihnen aufgebaut.

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

Diese drei Methoden basieren alle auf einer Beziehung .

Mit


Ergebnis: with() Gibt das Modellobjekt und die zugehörigen Ergebnisse zurück.

Vorteil: Es ist ein eifriges Laden, das das N + 1-Problem verhindern kann .

Wenn Sie den folgenden Eloquent Builder verwenden:

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

Laravel ändert diesen Code in nur zwei 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...);

Und dann führt Laravel die Ergebnisse des zweiten SQL anders als die Ergebnisse des ersten SQL nach Fremdschlüssel zusammen . Geben Sie endlich die Sammlungsergebnisse zurück.

Wenn Sie also Spalten ohne den Fremdschlüssel im Abschluss ausgewählt haben, ist das Beziehungsergebnis leer:

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
  }...
}]

Hat


Hasgibt das Objekt des Modells zurück, dessen Beziehung nicht leer ist .

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

Laravel ändert diesen Code in ein SQL :

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

wo hat


whereHasund orWhereHasMethoden, um whereBedingungen für Ihre hasAbfragen festzulegen. Mit diesen Methoden können Sie einer Beziehungsbeschränkung benutzerdefinierte Einschränkungen hinzufügen .

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

Laravel ändert diesen Code in ein SQL :

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
TsaiKoga
quelle