Assume we have a table like this users, posts, comments and replies. The relationship between them is a user has many posts and a post has many comments and the comment has many replies. Now we want to seed data with those tables together. How we can do that?

So if you do not know laravel 9 seed many to many relationship, one to one relationship and one to many relationship, then this llaravel factory seed nested relationship tutorial is going to be for you. In this tutorial, I will show you laravel factory seed nested relationship. If your laravel factory relationship not working then this tutorial will definitely help you.

laravel-nested-relationship-factory-seeder-example

Step 1: Create Model

Now we need four models like User,Post,Comment, and Reply. So create it by using the below command:

php artisan make:model Post -mf
php artisan make:model Comment -m
php artisan make:model Reply -m

 

Read also: Laravel 9 Factory Seed Many To Many Pivot Table

 

Step 2: Update Migration

Now we need to update our migration. So update it like this:

<?php

use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(User::class)
                ->constrained()
                ->cascadeOnUpdate()
                ->cascadeOnDelete();
            $table->mediumText('title')->unique();
            $table->boolean('is_published')->default(true);
            $table->timestamps();
        });
    }

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

 

Now update the comments table:

<?php

use App\Models\Post;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(Post::class)
                ->constrained()
                ->cascadeOnUpdate()
                ->cascadeOnDelete();
            $table->string('comment');
            $table->boolean('is_approved')->default(false);
            $table->timestamps();
        });
    }

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

 

Now update the replies table:

<?php

use App\Models\Comment;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('replies', function (Blueprint $table) {
            $table->id();
            $table->foreignIdFor(Comment::class)
                ->constrained()
                ->cascadeOnUpdate()
                ->cascadeOnDelete();
            $table->string('reply');
            $table->timestamps();
        });
    }

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

 

Step 3: Connect Database

After successfully installing the laravel app and then configuring the database setup. We will open the ".env" file and change the database name, username and password in the env file.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=Enter_Your_Database_Name
DB_USERNAME=Enter_Your_Database_Username
DB_PASSWORD=Enter_Your_Database_Password

 

Now run the command php artisan migrate to create those tables.

php artisan migrate

 

Step 4: Update model with relationship

Now in this step, we have to update the model with the relationship. Cause we are going to seed nested relationship data:

App\Models\User.php

<?php

namespace App\Models;

use Laravel\Sanctum\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

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

 

Now update the Post model:

App\Models\Post.php

<?php

namespace App\Models;

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

class Post extends Model
{
    use HasFactory;

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

 

Now update the Comment model:

App\Models\Comment.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Comment extends Model
{
    use HasFactory;

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

 

Now update the Reply model:

App\Models\Reply.php

<?php

namespace App\Models;

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

class Reply extends Model
{
    use HasFactory;

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

 

Step 5: Update DatabaseSeeder

Laravel by default provides UserFactory like:

Database\Factories\UserFactory.php

<?php

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
 */
class UserFactory extends Factory
{
    public function definition()
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
            'remember_token' => Str::random(10),
        ];
    }

    public function unverified()
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}

 

So now open DatabaseSeeder class and update it like:

Database\Seeders\DatabaseSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;

class DatabaseSeeder extends Seeder
{
    public function run()
    {   
        User::factory(20)->create()
            ->each(function($user){
            Post::create([
                'user_id' => $user->id,
                'title' => fake()->paragraph()
            ])->each(function($post){
                $post->comments()->create([
                    'comment' => fake()->sentence()
                ])->each(function($comment){
                    $comment->replies()->create([
                        'reply' => fake()->sentence()
                    ]);
                });
            });
        });
    }
}

 

All are set to go. Now run the below command and test:

php artisan db:seed

 

Read also: Laravel 9 Factory Seed One To Many Relationship Example

 

Conclusion

I have tried to discuss the clear concept of laravel factory seed nested relationship. Now we know how to solve laravel factory relationship not working. Hope this nested relationships with laravel faker tutorial will help you.