Laravel - Eloquent "Has", "With", "WhereHas" - Apa artinya?

212

Saya telah menemukan konsep dan makna di balik metode ini menjadi sedikit membingungkan, apakah mungkin bagi seseorang untuk menjelaskan kepada saya apa perbedaan antara hasdan withdalam konteks contoh (jika mungkin)?

lukasgeiter
sumber

Jawaban:

558

Dengan

with()untuk pemuatan yang cepat . Itu pada dasarnya berarti, di sepanjang model utama, Laravel akan melakukan preload hubungan yang Anda tentukan. Ini sangat membantu jika Anda memiliki koleksi model dan Anda ingin memuat relasi untuk semuanya. Karena dengan pemuatan yang cepat Anda hanya menjalankan satu permintaan DB tambahan alih-alih satu untuk setiap model dalam koleksi.

Contoh:

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
}

Memiliki

has()adalah menyaring model pemilihan berdasarkan suatu hubungan. Jadi itu bertindak sangat mirip dengan kondisi WHERE normal. Jika Anda hanya menggunakan has('relation')itu berarti Anda hanya ingin mendapatkan model yang memiliki setidaknya satu model terkait dalam hubungan ini.

Contoh:

User > hasMany > Post

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

Dimana

whereHas()bekerja pada dasarnya sama seperti has()tetapi memungkinkan Anda untuk menentukan filter tambahan untuk model terkait untuk diperiksa.

Contoh:

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
sumber
101
+1, jawaban yang sangat membantu! Perhatikan juga bahwa sementara with('relation')akan menyertakan data tabel terkait dalam koleksi yang dikembalikan, has('relation')dan tidakwhereHas('relation') akan menyertakan data tabel terkait. Jadi, Anda mungkin perlu untuk memanggil kedua serta atau . with('relation')has()whereHas()
Soulriser
1
Jawaban Greet, Cara mengakses model induk dari model hubungan misalnya di sini cara mencari model posting berdasarkan atribut model pengguna
hussainfrotan
@ BohojendraNepal Sayangnya sepertinya tidak ada banyak tentang hal itu di dokumen ... Ini yang saya temukan (beberapa paragraf ke bawah)
lukasgeiter
@hussainfrotan dengan cara yang sama, gunakan whereHaspada relasi pengguna saat meminta posting.
Michael Tsang
Penasaran, dalam dokumentasi Laravel: laravel.com/docs/5.8/eloquent-relationships , saat menggunakannya whereHasmenggunakan use Illuminate\Database\Eloquent\Builder;yang kemudian dengan function(Builder $query). Sebagian besar contoh yang saya lihat, gunakan titik Builder, cukup masukkan $ query, yang merupakan cara yang benar?
Guntar
8

Dokumen sudah menjelaskan penggunaannya. Jadi saya menggunakan SQL untuk menjelaskan metode ini

Contoh:


Anggap ada yang Order (orders)punya banyak OrderItem (order_items).

Dan Anda sudah membangun hubungan di antara mereka.

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

Ketiga metode ini didasarkan pada suatu hubungan .

Dengan


Hasil: with() mengembalikan objek model dan hasil terkait.

Keuntungan: Ini adalah bersemangat-loading yang dapat mencegah N + 1 masalah .

Saat Anda menggunakan Eloquent Builder berikut:

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

Laravel mengubah kode ini menjadi hanya dua 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...);

Dan kemudian laravel menggabungkan hasil dari SQL kedua sebagai berbeda dari hasil SQL pertama dengan kunci asing . Akhirnya mengembalikan hasil pengumpulan.

Jadi, jika Anda memilih kolom tanpa foreign_key di penutupan, hasil hubungan akan kosong:

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

Memiliki


Hasakan mengembalikan objek model yang hubungannya tidak kosong .

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

Laravel mengubah kode ini menjadi satu SQL :

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

dimana


whereHasdan orWhereHasmetode untuk menempatkan wherekondisi pada haskueri Anda . Metode ini memungkinkan Anda untuk menambahkan batasan khusus ke batasan hubungan .

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

Laravel mengubah kode ini menjadi satu SQL :

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