Laravel - Eloquent “Has”, “With”, “WhereHas” - Ne anlama geliyorlar?


212

Bu yöntemlerin arkasındaki kavram ve anlamı biraz kafa karıştırıcı buldum, birisinin bana arasındaki farkın ne olduğunu açıklaması mümkün mü has ve withbir örnek bağlamında (eğer mümkünse) içinde, nedir?

Yanıtlar:


557

İle

with()için istekli yükleme . Bu temel olarak, ana model boyunca Laravel, belirttiğiniz ilişkileri önceden yükleyeceği anlamına gelir. Bu, özellikle bir model koleksiyonunuz varsa ve hepsi için bir ilişki yüklemek istiyorsanız yararlıdır. Çünkü istekli yükleme ile koleksiyondaki her model için bir yerine bir ek DB sorgusu çalıştırın.

Misal:

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
}

Vardır

has()seçme modelini bir ilişkiye göre filtrelemektir. Yani normal bir WHERE durumuna çok benzer şekilde hareket eder. Eğer bunu kullanırsanız has('relation'), sadece bu ilişkide en az bir ilgili modeli olan modelleri elde etmek istersiniz.

Misal:

User > hasMany > Post

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

Nerede bulunuyor

whereHas()temel olarak aynı şekilde çalışır, has()ancak ilgili modelin kontrol etmesi için ek filtreler belirtmenize olanak tanır.

Misal:

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, çok yararlı bir cevap! Süre de unutmayın with('relation')döndü koleksiyonunda ilgili tablonun verilerini içerecektir has('relation')ve whereHas('relation')olacak değil , ilgili tablonun verileri içerir. Her iki çağrı gerekebilir Yani with('relation')yanı sıra has()ya whereHas().
Soulriser

1
Selam Yanıt, İlişki modelinden ana modele nasıl
erişilir?

@BhojendraNepal Ne yazık ki dokümanlar bu konuda çok fazla görünmüyor ... Tüm bulduğum bu (birkaç paragraf aşağı)
lukasgeiter

@hussainfrotan aynı şekilde, gönderiyi sorgularken whereHaskullanıcı ilişkisini kullanın .
Michael Tsang

Meraklı, Laravel belgelerinde: laravel.com/docs/5.8/eloquent-relationships , kullanırken whereHaso zaman use Illuminate\Database\Eloquent\Builder;hangisi ile kullanır function(Builder $query). Gördüğüm çoğu örnek, nokta kullanın Builder, sadece $ sorgusu geçmek, hangi doğru yol?
Guntar

8

Belge zaten kullanımı açıkladı. Bu yüzden bu yöntemleri açıklamak için SQL kullanıyorum

Misal:


Var olduğunu varsayarsak Order (orders)çok vardır OrderItem (order_items).

Ve zaten aralarındaki ilişkiyi kurdunuz.

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

Bu üç yöntemin hepsi bir ilişkiye dayanır .

İle


Sonuç: with() model nesnesini ve ilgili sonuçlarını döndürür.

Avantaj: Öyle istekli yükleme olabilir N + 1 sorunu önlemek .

Aşağıdaki Eloquent Builder'ı kullanırken:

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

Laravel bu kodu sadece iki SQL olarak değiştirir :

// 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...);

Ve sonra laravel birleşiyor ikinci SQL sonuçlarını farklı olarak ilk SQL sonuçlarına göre yabancı anahtarın . Sonunda toplama sonuçları iade.

Kapanışta foreign_key olmadan sütunlar seçtiyseniz, ilişki sonucu boş olur:

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

Vardır


Hasmodelin ilişkisinin boş olmadığı nesnesini döndürür .

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

Laravel bu kodu bir SQL olarak değiştirir:

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

Nerede bulunuyor


whereHasve sorgularınıza koşul orWhereHaskoyma yöntemleri . Bu yöntemler , bir ilişki kısıtlamasına özelleştirilmiş kısıtlamalar eklemenize izin verirwherehas .

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

Laravel bu kodu bir SQL olarak değiştirir :

select * from `orders` where exists (
    select * 
    from `order_items` 
    where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.