Table of Contents
Eager loading is an optimization technique in Laravel to reduce the number of database queries. By default, when retrieving data with relationships in Laravel, it uses lazy loading, which can result in the N+1 query problem. However, using eager loading, we can solve this issue by retrieving all the related data in a single query.
In a foreach loop, we can use eager loading to retrieve all the related data at once, rather than querying the database each time for related data. This can lead to significant improvements in performance, particularly when working with large datasets.
In this approach, we can use the with()
method to specify the related models we want to load. The with()
method accepts an array of related models, and it loads all of them at once. By using this method, we can avoid multiple database queries and optimize the application's performance.
Laravel uses the with()
function to achieve eager loading.
<code class="language-php">$children = <model>::with('<table column>')->get();
foreach ($children as $child) {
// do something with each $child
}
In the foreach loop, we can now work with each child model and access the loaded relationship without generating additional queries. This technique can improve performance and optimize database queries when working with large datasets.
In this article, we will explore how to use eager loading in a foreach loop in Laravel, along with some best practices and tips for optimization.
Set up lab environment
First, create a new Laravel project by running the following command in your terminal:
laravel new eager_loading
Next, navigate into the project directory by running:
cd eager_loading
Install Laravel Breeze by running the following command:
composer require laravel/breeze --dev
Next, run the following command to install Breeze into your Laravel project:
php artisan breeze:install
Create a new MySQL database called eager_loading by running the following command:
mysql -u root mysql> create database eager_loading; mysql> exit;
Run the following command to create the necessary tables in your database:
php artisan migrate
Install the necessary NPM dependencies by running:
npm install
Compile your assets by running:
npm run dev
Start the Laravel development server by running:
php artisan serve
Create a new model for your database table by running the following command:
php artisan make:model <ModelName>
Example - Using eager loading in foreach loop Laravel
We will register users in a Laravel application. The users can create posts after logging into respective dashboards. Using eager loading, we will fetch the users and their posts.
We create a new Laravel application called eager_loading
then install Breeze for user registration and logging. Next, we log in to a MySQL database and create a database. We then migrate the changes and start the development servers.
Register users
Now register three users.
- Lorem lorem@ipsum.com
- Mario mario@mario.com
- Jane jane@doe.net
Then, create the posts with their (database) relationships with their (author) users. First, let's create a Post model with its migration and controller.
Migrate posts table
php artisan make:model Post -mcr
Next, create the relationships in the respective models.
// User
public function posts() {
return $this->hasMany(Post::class);
}
//Post
public function user()
{
return $this->belongsTo(User::class);
}
Now create the blueprint of each post.
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->string('title');
$table->text('body');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
Then, migrate the changes.
php artisan migrate
Laravel Route and Controller for Post Creation and Storage
This code snippet includes the necessary routes and controller methods to create and store posts in Laravel. The create() method displays a form for the user to enter post details, and the store() method saves the post to the database with the currently authenticated user's ID.
// in routes/web.php
Route::get('/create', [PostController::class, 'create']);
Route::post('/store', [PostController::class, 'store']);
// in app/Http/Controllers/Post.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class PostController extends Controller
{
public function create()
{
return view('create');
}
public function store(Request $request)
{
$blog = new Post();
$blog->title = $request->title;
$blog->body = $request->body;
$blog->user_id = Auth::user()->id;
$blog->save();
return redirect('/');
}
}
Layout
This is an example code for creating a layout view for a Laravel app with Vite. It includes links to CSS and JS files and a navigation bar with links to home, create, and dashboard pages. The layout view is used as a template for other views to extend and fill in the content.
<!-- resources/views/components/layout.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 Demo Blog</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />
<!-- Styles -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="antialiased bg-slate-800 h-screen text-gray-200">
<nav class="w-full flex justify-around items-center bg-slate-900 h-16 mb-10">
<div>
<a class="text-xl" href="{{ url('/') }}">Home</a>
</div>
<div></div>
<ul class="flex space-x-6">
@if (Route::has('login'))
@auth
<li>
<a href="{{ url('/create') }}">Create</a>
</li>
<li>
<a href="{{ url('/dashboard') }}">Dashboard</a>
</li>
@else
<li>
<a href="{{ route('login') }}">Login</a>
</li>
@if (Route::has('register'))
<li>
<a href="{{ route('register') }}">Register</a>
</li>
@endif
@endauth
@endif
</ul>
</nav>
{{ $slot }}
</body>
</html>
Welcome
The code provided is an empty Blade view file located at resources/views/welcome.blade.php
that extends the layout
component by including the x-layout
Blade directive. The layout
component is defined in the resources/views/components/layout.blade.php
file and includes the basic HTML structure for the application's layout, such as the head
section with the necessary meta tags and stylesheets, and the body
section with the navigation menu and a slot to include the content specific to the current view.
<!-- resources/views/welcome.blade.php -->
<x-layout>
</x-layout>
Create
The form submits to the 'store' route using the POST method.
Inside the form, we have used the CSRF token using the '@csrf' Blade directive to protect against cross-site request forgery attacks. We have also used some Tailwind CSS classes to style the form elements.
<!-- resources/views/create.blade.php -->
<x-layout>
<form action="{{ url('store') }}" method="post" class="w-2/4 mx-auto">
@csrf
<div class="mb-4">
<label for="title" class="block mb-2">Title:</label>
<input type="text" name="title" class="w-full bg-gray-100 text-gray-700 p-2 rounded focus:outline-none sm:w-4/5">
</div>
<div class="w-full mb-4">
<label for="body" class="block mb-2">Body:</label>
<textarea name="body" id="body" rows="7" class="w-full bg-gray-100 text-gray-700 p-2 rounded focus:outline-none sm:w-4/5"></textarea>
</div>
<div class="mb-4">
<button class="bg-cyan-800 hover:bg-cyan-900 rounded px-8 py-2 ">Store</button>
</div>
</form>
</x-layout>
Now that a user can log in a create a post, let me show you how to load the users with their posts.
Eager loading users and posts
Route::get('/users', function () {
$users = User::with('posts')->get();
foreach ($users as $user) {
echo $user->name. '<br>';
echo '******<br>';
foreach ($user->posts as $post) {
echo $post->title. '<br>';
}
echo '............................<br><br>';
}
});
On hitting the /users
route, Laravel eagerly loads users with their posts. Using foreach
loop, we loop through each user and print their name and posts.
Conclusion
In this tutorial, we learned how to use eager loading in Laravel's foreach loop to improve application performance. Eager loading is a technique for loading related data together with the primary model, which avoids the N+1 query problem that occurs when we use the traditional method of loading related data inside a loop.
We started by defining eager loading and discussing the benefits of using it, including reducing the number of queries, improving application performance, and avoiding potential performance issues. Then we looked at a code example where eager loading is used to load posts along with their respective users, and we looped through each user and their posts. We also provided catchy title suggestions for articles related to the topic.
Next, you created a Laravel blog from scratch, registered, logged in, and authenticated each user before enabling them to create some posts. Lastly, you loaded all users and posts using Laravel eager loading.