Category : #laravel
Tags : #laravel, #database and migration
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.
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
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.