Use updateOrCreate() to Run Seeds At Any Time

Database seeding is a convenient function, but it is designed to run once, in the beginning of the project. What if later you want to add some new seeder and unable to run db:seed or migrate:fresh cause current data is already important? There's a cure.

Let's take an example, let's say you want to seed two Role entries, with database/seeds/RolesTableSeeder.php:

use Illuminate\Database\Seeder;

class RoleSeed extends Seeder
{
    public function run()
    {
        $items = [
            ['id' => 1, 'title' => 'Administrator'],
            ['id' => 2, 'title' => 'Simple user'],
        ];

        foreach ($items as $item) {
            Role::create($item);
        }
    }
}

You also seed and specify IDs as 1 and 2, because they are important to assign users to roles, later in the app.

Now, what if you want to change your Role name later in the project? Your options:

  • Create a migration file for that with Role::find(1)->update(); statement;
  • Create a specific seed file and run php artisan db:seed --class=NewRoleSeeder
  • Modify existing seeder and re-run php artisan db:seed for the whole app.

The last option seems impossible, because running the seed file above will cause an error that entry with ID 1 already exists.

Now, here's the trick that I've started using, whenever creating a seed file: use Eloquent updateOrCreate() instead of create() method.

Long version - checking if every record exists:

foreach ($items as $item) {
  $role = Role::find($item['id']);
  if ($role) {
    $role->update($item);
  } else {
    Role::create($item);
  }
}

Shorter version - with updateOrCreate():

foreach ($items as $item) {
    Role::updateOrCreate(['id' => $item['id']], $item);
}

Actually, same will help if you want to add more roles later in the project, you just add the third array item and pretty safely run php artisan db:seed again. Though, I would advise to perform a database backup beforehand, just in case.

More about updateOrCreate() and a few similar Eloquent methods - in the official Laravel documentation.

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 59 courses (1056 lessons, total 42 h 44 min)
  • 78 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent Premium Tutorials