The Ease of Eager-loading in Laravel
Tags: laravel, php, backend, webdev
Published: 2024-03-13 17:12:59

Ever waited for a webpage or app to load? That frustrating feeling when time seems to crawl by? That's the nightmare of today's digital world and a major buzzkill for users. Slow load times can derail the entire user experience, leading them to leave your website before even seeing its value.

That's a problem.

> 47% of users won't wait more than two seconds for a website to load
_- [Top Website Statistics of 2023 | Forbes](https://www.forbes.com/advisor/business/software/website-statistics/#:~:text=47%25%20of%20users)_

Thankfully, Laravel has a not-so-secret weapon for optimizing performance: Eager-loading.

## What is Eager-loading?
Eager-loading is like saying, "I'll need that later, so I'll grab it now." It's akin to packing a flashlight for a trip instead of going back for it when needed.

In database terms, eager-loading reduces the number of trips to fetch data, saving milliseconds that add up with complex applications.

[Eager-loading documentation](https://laravel.com/docs/5.2/eloquent-relationships#eager-loading)

## Eager-loading Prerequisites
In Laravel, eager-loading is built-in; no additional libraries are needed. However, proper setup of model relationships in the database and Laravel app is crucial.

### Setting Up Your Tables
Define primary and foreign keys in your database tables. For example:

``` php
// posts table
$table->primary('id');

// comments table
$table->primary('id');
$table->foreignId('post_id')->constrained('posts');
```

### Defining Your Relationships
Define relationships in models generated by php artisan make:model ModelName. For instance:

``` php
// App\Models\Post.php
public function comments(): HasMany
{
  return $this->hasMany(PostComments::class);
}

// App\Models\PostComment.php
public function post(): BelongsTo
{
  return $this->belongsTo(Post::class);
}
```

## Eager-loading in Action
Now, how do we eager-load these relationships? Use `$posts->load(['comments'])` to fetch posts and associated comments in one query.

Without eager-loading, separately fetching posts and comments would lead to multiple queries, impacting performance significantly.
Now, let's look at how you _could_ load posts and their comments without eager-loading.

In these examples, we'll act as though we're in a `IndexPostsController` where we'll query for _all_ posts _and_ their comments.

### Without Eager-loading
``` php
// without eager loading

public function __invoke()
{
  $posts = Post::all();

  foreach ($posts as $post) {
    $posts->comments = PostComment::where('post_id', $post->id);
  }

  return Inertia::render('IndexPosts',
    [
      'posts' => $posts
    ]
  );
}
```

### With Eager-loading

``` php
// with eager loading

public function __invoke()
{
  return Inertia::render('IndexPosts',
    [
      'posts' => $posts->load(['comments'])
    ]
  );
}
```
Eager-loading saves queries, improves performance, and enhances the user experience. Your database, you, and your users will thank you for building a fast-loading app!

Learn more about eager-loading [here](https://laravel.com/docs/10.x/eloquent-relationships#eager-loading) in the official Laravel documentation.