Tôi đã tìm thấy khái niệm và ý nghĩa đằng sau các phương thức này là một chút khó hiểu, liệu ai đó có thể giải thích cho tôi sự khác biệt giữa has
và with
trong bối cảnh của một ví dụ (nếu có thể) không?
Tôi đã tìm thấy khái niệm và ý nghĩa đằng sau các phương thức này là một chút khó hiểu, liệu ai đó có thể giải thích cho tôi sự khác biệt giữa has
và with
trong bối cảnh của một ví dụ (nếu có thể) không?
Câu trả lời:
with()
là cho tải háo hức . Điều đó về cơ bản có nghĩa là, dọc theo mô hình chính, Laravel sẽ tải trước (các) mối quan hệ bạn chỉ định. Điều này đặc biệt hữu ích nếu bạn có một bộ sưu tập các mô hình và bạn muốn tải một mối quan hệ cho tất cả chúng. Bởi vì với tải háo hức, bạn chỉ chạy một truy vấn DB bổ sung thay vì một truy vấn cho mọi mô hình trong bộ sưu tập.
Thí dụ:
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
}
has()
là để lọc mô hình lựa chọn dựa trên mối quan hệ. Vì vậy, nó hoạt động rất giống với một điều kiện WHERE bình thường. Nếu bạn chỉ sử dụng has('relation')
điều đó có nghĩa là bạn chỉ muốn lấy các mô hình có ít nhất một mô hình liên quan trong mối quan hệ này.
Thí dụ:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
whereHas()
hoạt động cơ bản giống như has()
nhưng cho phép bạn chỉ định các bộ lọc bổ sung cho mô hình liên quan để kiểm tra.
Thí dụ:
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
whereHas
trên quan hệ người dùng khi truy vấn bài.
whereHas
nó sẽ sử dụng use Illuminate\Database\Eloquent\Builder;
với function(Builder $query)
. Hầu hết các ví dụ mà tôi thấy, dấu chấm sử dụng Builder
, chỉ cần vượt qua trong truy vấn $, đó là cách đúng đắn?
Tài liệu đã giải thích việc sử dụng. Vì vậy, tôi đang sử dụng SQL để giải thích các phương thức này
Giả sử có một cái Order (orders)
có nhiều OrderItem (order_items)
.
Và bạn đã xây dựng mối quan hệ giữa họ.
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
Ba phương pháp này đều dựa trên một mối quan hệ .
Kết quả: with()
trả về đối tượng mô hình và các kết quả liên quan của nó.
Ưu điểm: Đây là háo hức nạp mà có thể ngăn chặn sự N + 1 vấn đề .
Khi bạn đang sử dụng Trình tạo Eloquent sau:
Order::with('orderItems')->get();
Laravel thay đổi mã này thành chỉ hai 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...);
Và sau đó laravel hợp nhất các kết quả của SQL thứ hai khác với kết quả của SQL đầu tiên bằng khóa ngoại . Cuối cùng trả lại kết quả thu thập.
Vì vậy, nếu bạn đã chọn các cột mà không có Foreign_key đóng, kết quả mối quan hệ sẽ trống:
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
}...
}]
Has
sẽ trả về đối tượng của mô hình mà mối quan hệ của nó không trống .
Order::has('orderItems')->get();
Laravel thay đổi mã này thành một SQL :
select * from `orders` where exists (
select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)
whereHas
và orWhereHas
phương pháp để đặt where
điều kiện vào các has
truy vấn của bạn . Các phương thức này cho phép bạn thêm các ràng buộc tùy chỉnh vào một ràng buộc mối quan hệ .
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel thay đổi mã này thành một SQL :
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
with('relation')
sẽ bao gồm dữ liệu của bảng có liên quan trong bộ sưu tập được trả vềhas('relation')
vàwhereHas('relation')
sẽ không bao gồm dữ liệu của bảng có liên quan. Vì vậy, bạn có thể cần phải gọi cả haiwith('relation')
cũng nhưhas()
hoặcwhereHas()
.