Laravel 11 Pagination with Relationship Tutorial Example

In Laravel 11, retrieving data from two or more tables has become more straightforward thanks to the Eloquent Relationships and the paginate() method. In this guide, we’ll develop a comprehensive example showing how to implement pagination in Laravel with Relation for these Models in a user-friendly way.

We’ll walk through the entire process, including setting up migrations and models, creating controllers and views, and populating data with Laravel’s artisan commands.

Step 1 – Create Models and Migrations

Begin by generating models and migrations for the tables:

php artisan make:model Category -m
php artisan make:model Post -m

Next, modify the database/migrations/_create_posts_table.php file to include the following schema:

public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug');
$table->text('body');
$table->foreignId('category_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}

Similarly, update database/migrations/_create_categories_table.php with:

public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}

Execute the migration command:

php artisan migrate

Step 2 – Define Model Relationships

In app/Models/Category.php, establish the relationship between categories and posts:

public function posts(): HasMany
{
return $this->hasMany(Post::class);
}

In app/Models/Post.php, define the inverse relationship:

public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}

Step 3 – Seed Dummy Data

Generate a seeder file to populate the tables with sample data:

php artisan make:seeder PostSeeder

Edit database/seeders/PostSeeder.php to include:

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\Category;
use Illuminate\Support\Str;

class PostSeeder extends Seeder
{
    public function run(): void
    {
        $cat1 = Category::create(['name' => 'Laravel']);
        $cat2 = Category::create(['name' => 'Laravel 11']);

        $posts = [
            [
                'title' => 'Laravel Product CRUD Tutorial',
                'body' => 'Step by Step Laravel Product CRUD Tutorial',
                'category_id' => $cat1->id
            ],
            [
                'title' => 'Laravel Image Upload Example',
                'body' => 'Step by Step Laravel Image Upload Example',
                'category_id' => $cat2->id
            ],
            [
                'title' => 'Laravel File Upload Example',
                'body' => 'Step by Step Laravel File Upload Example',
                'category_id' => $cat2->id
            ],
            [
                'title' => 'Laravel Cron Job Example',
                'body' => 'Step by Step Laravel Cron Job Example',
                'category_id' => $cat1->id
            ],
            [
                'title' => 'Laravel Send Email Example',
                'body' => 'Step by Step Laravel Send Email Example',
                'category_id' => $cat1->id
            ]
        ];

        foreach ($posts as $post) {
            Post::create([
                'title' => $post['title'],
                'slug' => Str::slug($post['title']),
                'body' => $post['body'],
                'category_id' => $post['category_id'],
            ]);
        }
    }
}

Run the seeder to populate the database:

php artisan db:seed --class=PostSeeder

Step 4 – Add Routes

In routes/web.php, add a route to handle pagination:

use App\Http\Controllers\PostController;

Route::get('posts', [PostController::class, 'index']);

Step 5 – Create the Controller

Generate a controller to handle business logic:

php artisan make:controller PostController

Edit app/Http/Controllers/PostController.php to include pagination with related data:

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostController extends Controller
{
public function index(Request $request)
{
$posts = Post::with('category')->paginate(4);

return view('posts', compact('posts'));
}
}

Step 6 – Create the Blade View

Create resources/views/posts.blade.php to display the paginated data:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel 11 Pagination with Relationship Tutorial</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css">
</head>
<body>

<div class="container mt-5">

<div class="card mt-5">
<h3 class="card-header p-4">Laravel 11 Pagination with Relationship tutorial</h3>
<div class="card-body mt-4">
<div class="row">
@foreach($posts as $post)
<div class="col-md-3">
<div class="card mt-2" style="width: 18rem;">
<img src="https://picsum.photos/id/0/367/267" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{ $post->title }}</h5>
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
<button class="btn btn-primary">{{ $post->category->name ?? '' }}</button>
</div>
</div>
</div>
@endforeach
</div>

<div class="mt-3">
{{ $posts->links('pagination::bootstrap-5') }}
</div>
</div>
</div>
</div>

</body>
</html>

Step 7 – Test the Application

Start the Laravel development server:

php artisan serve

Navigate to http://localhost:8000/posts in your browser to view the paginated posts with their respective categories.