Eager Loading
16477

# 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
  1. 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);
        }
    }
    

     

  2. 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);
        }
    }
    
  3. 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');
    });
    
  4. 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
        }
    }
    
  5. 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ụng withCount để 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ệ.

    // 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
    }
    
    5.3 Eager Load Với Điều Kiệ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
  1. 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);
        }
    }
    

     

  2. 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');
        }
    }
    
  3. 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');
        }
    }
    
  4. 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);
        }
    }
    
  5. 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();
    });
    
  6. 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ức with được sử dụng để eager load các quan hệ comments và trong comments, eager load user (người dùng bình luận) và commentable (model mà bình luận thuộc về, có thể là Post hoặc Video).
    • 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


  1. Khác
  2. ThreeJS
  3. Ubuntu/Linux
  4. HTML/CSS
  5. Git
  6. Amazon Web Services
  7. Javascript
  8. Docker
  9. Laravel

Bài viết liên quan


Quản Lý Thời Gian Tự Động Trong Eloquent

Quản Lý Thời Gian Tự Động Trong Eloquent

01.08.2024
Author: ADMIN
Khám phá cách quản lý timestamps trong Eloquent Laravel: tắt tự động cập nhật, tùy chỉnh định dạng, đổi tên cột và cập nhật dữ liệu mà không ảnh hưởng updated_at.
Các Mối Quan Hệ Trong Eloquent

Các Mối Quan Hệ Trong Eloquent

01.08.2024
Author: ADMIN
Tìm hiểu cách thiết lập và sử dụng các mối quan hệ trong Eloquent Laravel, giúp quản lý dữ liệu dễ dàng và linh hoạt hơn.
Basic Eloquent Model and MVC

Basic Eloquent Model and MVC

01.08.2024
Author: ADMIN
Tìm hiểu cách Laravel triển khai kiến trúc MVC với Model, View, Controller. Hướng dẫn chi tiết về Eloquent, xử lý logic trong Controller và hiển thị dữ liệu với Blade.
Database: Seeding

Database: Seeding

01.08.2024
Author: ADMIN
Laravel Seeding giúp tự động tạo dữ liệu mẫu nhanh chóng. Tìm hiểu cách tạo, chạy seeder, kết hợp factory, và sử dụng trong production một cách an toàn! 🚀

Bài viết khác

Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

01.08.2024
Author: ADMIN
Khám phá 9 mẹo Blade giúp bạn viết code Laravel sạch, tối ưu và chuyên nghiệp hơn. Từ @forelse, @auth, @guest, đến format ngày, tối ưu SEO – tất cả trong một bài viết súc tích, dễ áp dụng!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!