2-laravel-advanced-laravel-lazy-load-and-eager-load-61249858a8f431629788248.jpg

Laravel Advanced - #2 Laravel Lazy Load and Eager Load

Laravel

Subhadip Ghorui

2 years ago

Subhadip Ghorui

Watch Video:

 

Lazy Loading

 

If additional constraints to an Eloquent relationship query are not needed at first, we can simply access the relationship as if it were a property of that model. Like in here we have a Post model and it belongs to only one Category. To get the category we can simply access it in the blade templet. Because we access it later, not the time of the posts query it’s called Lazy loading.

$posts = Post::all();

Access later

@foreach ($posts as $post)

{{$post->title}}

{{$post->category->name}}

@endforeach

Lazy Load - myiotlab.in

The process will loop all records in houses and execute 1 query for each loop to get the city data, for example that we have 5 records of posts, the query to get the data in the relationship table will execute 5 times + 1 original query for getting the house data, the time of query for “Lazy loaded” is N+1.

 

Eager Loading

Eager loading initializes or loads a resource as soon as the code is executed. However, Eloquent can “eager load” relationships at the time you query the parent model. Eager loading solved the N + 1 query problem and it is very usefull when we make API and send additional relationship data. Because the API sends data as JSON, we cannot use php there. So eager loading is the only way to do this.

$posts = Post::with(‘category’)->get();

 

When we access later it solved n+1 problem:

@foreach ($posts as $post)

{{$post->title}}

{{$post->category->name}}

@endforeach

 

Eager Loading - myiotlab

We can see our queries have been reduced from 6 to 2. First server loads the posts then loads all categories for the post's ids in the next query.

 

Lazy load and Eager load in Laravel

 

1. Project Setup

For this tutorial, we will be using the same app which we build in the previous tutorial (post link).

We create some posts with category.

Database/migrations

Posts migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('category_id')->nullable();
            $table->text('title');
            $table->text('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

 

Category migration -

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('about');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }

 

Post Model - 

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    // protected $guarded = [];
    protected $fillable = ['title', 'body'];

    public function category(){
        return $this->belongsTo('App\Models\Category');
    }
}

 

Category Model -

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    public function posts(){
        return $this->hasMany('App\Models\Post');
    }
}

 

PostController -

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        // return response($posts,200);
        return view('posts.index', compact('posts'));

    }

}

 

Posts View

index.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

        <style>
            body {
                font-family: 'Nunito', sans-serif;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="row my-5">
               <div class="col p-2">
                <h1>Posts</h1>
               </div>
            </div>
            <div class="row d-flex justify-content-center">
                <div class="col-12">
                    @foreach ($posts as $post)
                    <div class="card my-2">
                       <div class="card-body">
                        <h2 class="text-dark">{{$post->title}}</h2>
                        <h4 class="text-success"><b>{{$post->category->name}}</b></h4>
                        <div class="card-text">{{$post->body}}</div>
                      </div>
                    </div>
                    @endforeach
                </div>
            </div>
        </div>
        {{-- JS --}}
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
    </body>
</html>

 

2. Eager Loading in Laravel 8

We can eager load from Controller and if you want to eager load by default define it on Model.

Setup in Controller

 public function index()
    {
        $posts = Post::with('category:id,name')->get();

        return view('post.index',compact('posts'));
        // return response($posts);
    }

Use with(‘category’) method to load relationship data. You can specify the attribute of that relationship data with(‘category:id,name’). Remember id is mandatory when define attributes.

 

Setup in Model

You can setup it also in Model.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    // protected $guarded = [];
    protected $fillable = ['title', 'body'];

    protected $with = ['category:id,name'];

    public function category(){
        return $this->belongsTo('App\Models\Category');
    }
}

If you do the same with the category model Don’t forget to define the attributes you want to eager load (Explain) in the video.

Do not forget to like and share this post.

⭐GitHub Repository:  https://github.com/subhadipghorui/laravel-advanced-topics

 

0 people like this
6108 views
0 comments
Share it on your social media account.

Please Sign in to post comments - Sing in or Register

0 Comments