Khi làm việc với framwork Laravel, bài toán rất hay gặp phải đó là lấy dữ liệu từ một model được liên kết với một model. Trong Laravel có 2 cách tiếp cận rất quan trọng để giải quyết vấn đề này được gọi là Eager Loading thông qua 2 hàm kinh điển đó là with() và load(). Vậy nó là gì, và sử dụng chúng như thế nào. Chúng ta sẽ cùng xem tiếp nhé.
Cả 2 phương thức with() và load() đều trả về cùng một kết quả giống nhau. Đó là load dữ liệu một model có quan hệ tới một model khác. Một sự giống nhau nữa là cả hai đều chạy 2 câu query. Vậy đâu là điểm khác biệt giữa hai hàm này.
Điểm khác biệt ở đây chính là thời điểm model relation được load. Nếu như hàm with() sẽ thực thi ngay sau truy vấn đầu tiên và khi nó gặp các phương thức dạng như get(), fitst(), all()… Hiểu đơn giản thì with() sẽ load cùng thời điểm với model cha. Còn đối với phương thức load(), nó sẽ thực hiện câu query trước và sẽ load các mối quan hệ ở thời điểm sau này. Có lẽ vẫn hơi khó hình dung, sau đây chúng ta sẽ cùng đi một ví dụ cụ thể để hiểu rõ hơn về hai khái niệm này nhé.
1. Eager loading using with()
Ví dụ:
$users = User::with('comments')->get();
Giả sử chúng ta có 5 users, thì 2 câu query sau sẽ chạy ngay lập tức:select * from `users`
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
Chúng ta đã sử dụng phương thức get() ở cuối câu lệnh lấy thông tin users, nó trả về một collection đã đính kèm thông tin của model comments liên quan. Do đó, để lấy thông tin comments đầu tiên chúng ta có thể làm như sau: $users->comments->first()->body
2. “Lazy” eager loading using load()
Đối với phương thức load() chúng ta sẽ làm như sau:
$users = User::all();
Lúc này sẽ chạy câu sql:
select * from users
Sau đó bài toán đặt ra chúng ta cần lấy tất cả comments của tất cả users thì ta làm như sau:
if($someCondition){
$users = $users->load('comments');
}
Lúc này, câu query sau sẽ được chạy:
select * from `comments` where `comments`.`user_id` in (1, 2, 3, 4, 5)
Kết quả vẫn tương tự như với việc sử dụng with()
3. Sự khác nhau
– with() hay còn gọi là eager loading lấy tất cả data và quan hệ của tất cả data đó tại 1 thời điểm. Trong khi đó load() sẽ sử dụng N+1 câu query (gồm câu query lấy data và sử dụng hàm load() trong vòng lặp) cho việc lấy data và dữ liệu liên quan
– with() chạy 2 câu query trong khi load chạy N+1 câu query
– with() cho tốc độ cực nhanh và tốn ít bộ nhớ hơn so với load()