Using seeder and factory to create dummy data for pivot table

Suppose there are three tables communities, topics, posts and one pivot table community_topic ( in singular ).

Hence if we want to draw relationship of many to many between communities and topics that is one commnunity can have many topics and on the other hand one topic also can relate to many communities, we need to follow given snippets below step by step to implement it.

Step 01: create fresh laravel project

composer create-project laravel/laravel communityBlog

Step 02: Setting Up scaffolding migration, factory, seeder of Community, Post and Topic model with artisan command

php artisan make:model Community -mfs
php artisan make:model Post -mfs
php artisan make:model Topic -ms

Step 03: Setting up scaffolding migration of pivot table community_topic

php artisan make:migration create_community_topic_table

Step 04: Setting up database and updating db config in .env file

DB_DATABASE=laravel_seeding_pivot_table

Step 05: Specifying migration definition in database\migrations\2022_09_22_203833_create_communities_table.php

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

Step 06: Specifying migration definition in database\migrations\2022_09_22_203904_create_topics_table.php

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

Step 07: Specifying migration definition in database\migrations\2022_09_22_203917_create_posts_table.php

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->foreignId('community_id')->constrained();
        $table->foreignId('topic_id')->constrained();
        $table->string('title');
        $table->text('post_text')->nullable();
        $table->timestamps();
        $table->softDeletes();
    });
}

Step 08: Specifying migration definition in database\migrations\2022_09_22_204130_create_community_topic_table.php

public function up()
{
    Schema::create('community_topic', function (Blueprint $table) {
        $table->foreignId('community_id')->constrained();
        $table->foreignId('topic_id')->constrained();
    });
}

Step 09: Setting up Community model in App\Models\Community.php

class Community extends Model
{
    use HasFactory;

    protected $fillable = [ 'name', 'description'];

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

Step 10: Setting up Post model in App\Models\Post.php

class Post extends Model
{
    use HasFactory;

    protected $fillable = [ 'community_id', 'topic_id',  'title', 'post_text'];

    public function community()
    {
        return $this->belongsTo(Community::class);
    }

    public function topic()
    {
        return $this->belongsTo(Topic::class);
    }

}

Step 11: Setting up Topic model in App\Models\Topic.php

class Topic extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'description'];

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

    public function community()
    {
        return $this->belongsToMany(Community::class);
    }       
}

Step 12: Specifying column rules for Community model in CommunityFactory.php

public function definition()
{
    //$name = fake()->name();
    
    return [
        'name' => $this->faker->text(200),
        'description' => $this->faker->text(500),
    ];
}

Step 13: Specifying column rules for Post model in PostFactory.php

use App\Models\Community;
use App\Models\Topic;

public function definition()
{
    $communityIds = Community::pluck('id');
    $topicIds = Topic::pluck('id');
    
    return [
        'community_id' => $communityIds->random(),
        'topic_id' => $topicIds->random(),
        'title' => $this->faker->text(50),
        'post_text' => $this->faker->text(500),
    ];
}

Step 14: Specifying definition of CommunitySeeder.php

use App\Models\Community;
use App\Models\Topic;

public function run()
{
    //
    Community::factory(100)->create();

    $communities = Community::all();
    $topics = Topic::pluck('id');

    foreach( $communities as $community ) {
        // attaching ( with attach method ) fetched random topic ( topicId only )
        // to each of the newly created community
        // with configured topics() relation
        $community->topics()->attach($topics->random());
    }
}

Step 15: Specifying definition of PostSeeder.php

public function run()
{
    Post::factory()->times(200)->create();
}

Step 16: Specifying definition of TopicSeeder.php

public function run()
{
    Topic::create(['name' => 'America']);
    Topic::create(['name' => 'Asia']);
    Topic::create(['name' => 'Africa']);
    Topic::create(['name' => 'Australia']);
    Topic::create(['name' => 'Europe']);
}

Step 17: Running TopicSeeder, CommunitySeeder and PostSeeder using run() method in DatabaseSeeder.php,  to run seed data for communities, topics, posts and community_topic table.

public function run()
{
    $this->call(TopicSeeder::class);
    $this->call(CommunitySeeder::class);
    $this->call(PostSeeder::class);
}

Relations in these seeding and factories are mentioned below.

1. community hasMany topics
2. topics hasMany communities
3. post belongsTo community and topic
4. community hasMany posts
5. topic hasMany posts

Step 18: Finally running following artisan command to run migration and seeding database tables.

php artisan migrate:fresh --seed

Execution of above command, in communities table there will be 100 communities created and in Posts table there will be 200 posts with randomly assigned community and topic. There will be only five rows of data in topics table.

Lastly, pivot table community_topic will hold 100 rows of community data with randomly assigned topic.

Related Posts