
# Eager Loading
Eager loading là một kỹ thuật trong Eloquent ORM của Laravel để giảm số lượng truy vấn đến cơ sở dữ liệu bằng cách tải các quan hệ của model ngay lập tức khi bạn truy vấn model chính. Điều này giúp cải thiện hiệu suất ứng dụng bằng cách tránh vấn đề N+1 queries, nơi bạn thực hiện nhiều truy vấn không cần thiết khi tải các quan hệ.
Ví Dụ: Eager Loading với Mối Quan Hệ Một-Nhiều
Giả sử bạn có một model Post
và mỗi bài viết có nhiều Comment
. Khi bạn muốn lấy tất cả các bài viết cùng với các bình luận của chúng, bạn có thể sử dụng eager loading để giảm số lượng truy vấn SQL.
Model và Cấu Trúc Bảng
-
Model
Post
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * Thiết lập mối quan hệ một-nhiều với Comment. */ public function comments() { return $this->hasMany(Comment::class); } }
- Model
Comment
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Comment extends Model { /** * Thiết lập mối quan hệ nhiều-một với Post. */ public function post() { return $this->belongsTo(Post::class); } }
- Cấu Trúc Bảng
Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->timestamps(); }); Schema::create('comments', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('post_id'); $table->text('content'); $table->timestamps(); $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade'); });
- Sử Dụng Eager Loading
4.1 Truy Vấn Bình Thường (Lazy Loading)
// Lấy tất cả bài viết $posts = Post::all(); // Truy xuất các bình luận của mỗi bài viết (N+1 queries) foreach ($posts as $post) { foreach ($post->comments as $comment) { // Xử lý bình luận } }
4.2 Sử Dụng Eager Loading
// Lấy tất cả bài viết cùng với các bình luận của chúng (1 query cho bài viết + 1 query cho bình luận) $posts = Post::with('comments')->get(); // Truy xuất các bình luận của mỗi bài viết mà không thực hiện thêm truy vấn foreach ($posts as $post) { foreach ($post->comments as $comment) { // Xử lý bình luận } }
- Các Tùy Chọn Eager Loading
5.1 Chỉ Định Các Quan Hệ Nâng Cao
Bạn có thể eager load nhiều quan hệ hoặc nested quan hệ (quan hệ trong quan hệ) bằng cách chỉ định chúng trong phương thức
with
.// Eager load các quan hệ bình luận và user của mỗi bình luận $posts = Post::with('comments.user')->get();
5.2 Sử Dụng
withCount
Bạn có thể sử dụngwithCount
để lấy số lượng các quan hệ mà không cần phải lấy dữ liệu chi tiết của quan hệ.
5.3 Eager Load Với Điều Kiện// Lấy số lượng bình luận cho mỗi bài viết $posts = Post::withCount('comments')->get(); foreach ($posts as $post) { echo $post->comments_count; // Số lượng bình luận }
// Eager load bình luận với điều kiện chỉ lấy những bình luận mới nhất $posts = Post::with(['comments' => function ($query) { $query->where('created_at', '>', now()->subDays(7)); }])->get();
# Nested Eager Loading morphTo Relationships
Khi làm việc với các mối quan hệ polymorphic trong Eloquent, bạn có thể cần thực hiện eager loading không chỉ cho các mối quan hệ polymorphic mà còn cho các mối quan hệ liên quan đến các model mà chúng liên kết đến. Đây được gọi là nested eager loading.
Mối Quan Hệ Polymorphic (morphTo) cho phép một model liên kết với nhiều model khác và không cần phải tạo nhiều cột khóa ngoại. Khi sử dụng eager loading với các mối quan hệ polymorphic, bạn có thể tải tất cả các dữ liệu cần thiết trong một truy vấn hiệu quả.
Ví Dụ: Nested Eager Loading với Mối Quan Hệ Polymorphic
Giả sử bạn có một hệ thống bình luận mà mỗi bình luận có thể thuộc về nhiều loại model khác nhau (như Post
hoặc Video
). Đồng thời, mỗi bình luận có thể được gán cho một người dùng (user). Dưới đây là cách bạn có thể thiết lập và thực hiện nested eager loading cho các mối quan hệ này.
Cấu Trúc và Model
-
Model
Comment
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Comment extends Model { /** * Thiết lập mối quan hệ polymorphic. */ public function commentable() { return $this->morphTo(); } /** * Thiết lập mối quan hệ nhiều-một với User. */ public function user() { return $this->belongsTo(User::class); } }
- Model
Post
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { /** * Thiết lập mối quan hệ một-nhiều polymorphic với Comment. */ public function comments() { return $this->morphMany(Comment::class, 'commentable'); } }
- Model
Video
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Video extends Model { /** * Thiết lập mối quan hệ một-nhiều polymorphic với Comment. */ public function comments() { return $this->morphMany(Comment::class, 'commentable'); } }
- Model
User
namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Thiết lập mối quan hệ một-nhiều với Comment. */ public function comments() { return $this->hasMany(Comment::class); } }
- Cấu Trúc Bảng
Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->timestamps(); }); Schema::create('videos', function (Blueprint $table) { $table->id(); $table->string('title'); $table->timestamps(); }); Schema::create('comments', function (Blueprint $table) { $table->id(); $table->unsignedBigInteger('commentable_id'); $table->string('commentable_type'); $table->unsignedBigInteger('user_id'); $table->text('content'); $table->timestamps(); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); }); Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps(); });
- Thực Hiện Nested Eager Loading
// Lấy tất cả các bài viết cùng với bình luận của chúng, bình luận có người dùng và video hoặc bài viết liên quan $posts = Post::with(['comments.user', 'comments.commentable'])->get(); foreach ($posts as $post) { foreach ($post->comments as $comment) { echo $comment->content; // Nội dung bình luận echo $comment->user->name; // Tên người dùng bình luận echo $comment->commentable->title; // Tiêu đề của video hoặc bài viết liên quan } }
Giải Thích:
Post::with(['comments.user', 'comments.commentable'])->get();
: Phương thứcwith
được sử dụng để eager load các quan hệcomments
và trongcomments
, eager loaduser
(người dùng bình luận) vàcommentable
(model mà bình luận thuộc về, có thể làPost
hoặcVideo
).- Trong ví dụ này, khi bạn truy xuất các bài viết và bình luận, tất cả các dữ liệu liên quan đến bình luận và người dùng bình luận, cùng với model liên quan của bình luận (có thể là bài viết hoặc video) sẽ được tải ngay lập tức, giúp giảm số lượng truy vấn đến cơ sở dữ liệu.
Danh mục
Bài viết liên quan

Quản Lý Thời Gian Tự Động Trong Eloquent
Author: | ADMIN |
---|

Các Mối Quan Hệ Trong Eloquent
Author: | ADMIN |
---|

Basic Eloquent Model and MVC
Author: | ADMIN |
---|

Database: Seeding
Author: | ADMIN |
---|
Bài viết khác

Blade Basics
Author: | ADMIN |
---|

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel
Author: | ADMIN |
---|

Hiển thị giá trị trong Blade
Author: | ADMIN |
---|