Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Darkdawg's avatar

Seed required production data, how?

I'm working on a project where I'll be having user roles.

Some specific roles should exist on production after deployment, for example "admin" and "guest". What's the proper way to insert this data?

Currently I have it inside the migrations file, inside the up() method right after the Schema:

DB::table('roles')->insert([
    ['name' => 'admin', 'description' => 'Administrator with full access'],
    ['name' => 'guest', 'description' => 'Guest user'],
]);

Buuuut... I know migrations are intended for structure and not data. I could also use a seeder and detect environment, but I'm not sure I fancy that approach either. Last option would of course be to manually insert the roles after deployment.

Anything I'm missing? Which approach is recommended?

1 like
8 replies
vincent15000's avatar

IMHO it would be a good idea to use a seeder and execute it manually after each installation on a server.

Darkdawg's avatar

@vincent15000 Yeah maybe that's the best approach. I just didn't want to have separate production & dev seeders as that could cause confusion.

1 like
vincent15000's avatar

@Darkdawg I sometimes have 2 different seeders : a dev seeder and a prod seeder.

And inside each one, I call the needed seeders according to what I need.

Snapey's avatar

You can write it into a migration file, that way it only runs once.

1 like
martinbean's avatar

@darkdawg You can insert required records in your migration files themselves:

public function up(): void
{
    Schema::create('roles', function (Blueprint $table) {
        // Schema definition...
    });

    DB::table('roles')->insert([
        ['name' => 'admin', 'description' => 'Administrator with full access'],
        ['name' => 'guest', 'description' => 'Guest user'],
    ]);
}

This way, subsequent migrations don’t fail if they’re expecting particular “look-up” records like these to exist, since you can’t arbitrarily stop a migration run to go off and run a seeder, and then carry on migrating.

1 like
newbie360's avatar

I'm not agree insert data in migration ;( because it cause Testing preloaded unwanted data.

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        if (app()->isLocal()) {
            $this->call([
                RoleSeeder::class,
				// ... more seeder
            ]);
        } else {
            $this->call([
                // RoleSeeder::class,
				// ... more seeder
            ]);
        }
    }
}
bak0's avatar

Best approach is to use seeders and make sure there are not duplicates with Eloquent firstOrCreate method.

Please or to participate in this conversation.