Laravel 12 One-to-Many Eloquent Relationship

Hi there! If you're working with Laravel 12 and need to set up a one-to-many relationship between database tables, this guide is for you. In this beginner-friendly tutorial, I’ll show you how to use Laravel’s Eloquent ORM to create a one-to-many relationship.

We’ll use a practical example: a User who can have many Posts. By the end, you’ll know how to define models, migrations, relationships, and retrieve related data.

Laravel 12 One-to-Many Eloquent Relationship

What is a One-to-Many Relationship?

In a one-to-many relationship, a single record in one table can be associated with multiple records in another table. For example:

  • A User can have many Posts.
  • Each Post belongs to one User.

This is perfect for scenarios like blog posts, comments, or orders tied to a single user.

Prerequisites

Before starting, ensure you have:

  • A Laravel 12 project set up.
  • A database configured (e.g., MySQL, SQLite).
  • Basic knowledge of Laravel models, migrations, and controllers.

If you don’t have a project, create one with:

laravel new example-app

Step 1: Set Up the Database and Migrations

We’ll create two tables: users and posts. The posts table will have a foreign key linking to the users table.

Create the Users Migration

Laravel provides a default users migration. Check database/migrations to ensure it exists and looks like this:

<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('users');
    }
};

Create the Posts Migration

Run this command to create a migration for the posts table:

php artisan make:migration create_posts_table

Open the generated migration file in database/migrations and update it:

<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Explanation:

  • user_id is a foreign key linking to the users table.
  • onDelete('cascade') ensures that if a user is deleted, their posts are also deleted.
  • title and content store the post data.

Run the Migrations

Run the migrations to create the tables:

php artisan migrate

Step 2: Create the Models

Next, define the User and Post models and set up their relationships.

Update the User Model

Open app/Models/User.php and add the hasMany relationship:

<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Database\Eloquent\Relations\HasMany;

class User extends Authenticatable
{
    protected $fillable = ['name', 'email', 'password'];

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

Explanation: The hasMany method indicates that a User can have multiple Posts.

Create the Post Model

Run this command to create the Post model:

php artisan make:model Post

Open app/Models/Post.php and add the belongsTo relationship:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    protected $fillable = ['user_id', 'title', 'content'];

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

The belongsTo method indicates that a Post belongs to a User.

Step 3: Set Up Routes and Controller

Let’s create a controller to test the one-to-many relationship and a route to access it.

Create a Controller

Run:

php artisan make:controller UserController

Open app/Http/Controllers/UserController.php and add:

<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    public function index()
    {
        // Create a user
        $user = User::create([
            'name' => 'Jane Doe',
            'email' => '[email protected]',
            'password' => bcrypt('password'),
        ]);

        // Create posts for the user
        $user->posts()->createMany([
            [
                'title' => 'First Post',
                'content' => 'This is my first post!',
            ],
            [
                'title' => 'Second Post',
                'content' => 'This is my second post!',
            ],
        ]);

        // Retrieve the user with their posts
        $userWithPosts = User::with('posts')->first();

        return response()->json([
            'user' => $userWithPosts->name,
            'email' => $userWithPosts->email,
            'posts' => $userWithPosts->posts->map(function ($post) {
                return [
                    'title' => $post->title,
                    'content' => $post->content,
                ];
            }),
        ]);
    }
}

Explanation:

  • Creates a user and associates multiple posts using createMany.
  • Uses with('posts') to eager-load the posts.
  • Returns a JSON response with the user and their posts.

Define a Route

Open routes/web.php and add:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;

Route::get('/test-relationship', [UserController::class, 'index'])->name('test.relationship');

Step 4: Test the Relationship

Start your Laravel server:

php artisan serve

Visit http://localhost:8000/test-relationship in your browser. You should see a JSON response like:

{
    "user": "Jane Doe",
    "email": "[email protected]",
    "posts": [
        {
            "title": "First Post",
            "content": "This is my first post!"
        },
        {
            "title": "Second Post",
            "content": "This is my second post!"
        }
    ]
}

This confirms the one-to-many relationship is working!

Step 5: Using the Relationship in Your Application

You can access related data in various ways:

Retrieve a User’s Posts

$user = User::find(1);
$posts = $user->posts; // Returns a collection of Posts
foreach ($posts as $post) {
    echo $post->title; // Outputs: First Post, Second Post
}

Retrieve a Post’s User

$post = Post::find(1);
$user = $post->user; // Returns the associated User
echo $user->name; // Outputs: Jane Doe

In a Blade Template

Create a Blade file resources/views/user.blade.php:

<!DOCTYPE html>
<html>
<head>
    <title>Laravel 12 One-to-Many Relationship</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-5">
        <h3>{{ $user->name }}'s Posts</h3>
        <p><strong>Email:</strong> {{ $user->email }}</p>
        <h4>Posts:</h4>
        <ul>
            @foreach ($user->posts as $post)
                <li>
                    <strong>{{ $post->title }}</strong>: {{ $post->content }}
                </li>
            @endforeach
        </ul>
    </div>
</body>
</html>

Update the UserController to return the view:

public function index()
{
    $user = User::with('posts')->first();
    return view('user', compact('user'));
}

 

Conclusion

Implementing a one-to-many relationship in Laravel 12 is simple with Eloquent ORM! This tutorial showed you how to create migrations, define models, set up relationships, and retrieve related data using a User and Posts example.

Whether you’re building a blog, forum, or any app with related data, this approach keeps your database organized and efficient. I hope this guide was clear and helps you add one-to-many relationships to your Laravel projects.

Frequently Asked Questions (FAQs)

Q1: What’s the difference between hasMany and belongsTo?
A: hasMany is used on the model that owns multiple records (e.g., User has many Posts). belongsTo is used on the model that is owned (e.g., Post belongs to a User).

Q2: Why use a separate posts table?
A: A separate table organizes data better and allows a user to have multiple posts without cluttering the users table. It’s also more scalable for large datasets.

Q3: What does onDelete('cascade') do?
A: It ensures that if a user is deleted, all their associated posts are also deleted, maintaining data integrity.

Q4: How do I handle users with no posts?
A: The posts relationship returns an empty collection if no posts exist. You can check with @if($user->posts->isEmpty()) in Blade or $user->posts->isEmpty() in PHP.

Q5: Can I eager-load posts to improve performance?
A: Yes! Use User::with('posts') to load posts in one query, reducing database queries compared to lazy loading.


You might also like:

techsolutionstuff

Techsolutionstuff | The Complete Guide

I'm a software engineer and the founder of techsolutionstuff.com. Hailing from India, I craft articles, tutorials, tricks, and tips to aid developers. Explore Laravel, PHP, MySQL, jQuery, Bootstrap, Node.js, Vue.js, and AngularJS in our tech stack.

RECOMMENDED POSTS

FEATURE POSTS