S_R
S_R

Reputation: 1998

Laravel Insert Seed if data doesn't already exist

Is there any way to run a laravel seed to only insert the records if they do not exist already?

My current laravel seeder looks like this

DB::table('users')->insert([
                //Global Admin
                [
                    'member_id' => 11111111,
                    'firstname' => 'Joe',
                    'lastname' => 'Bloggs'
                ], 
                [
                    'member_id' => 22222222,
                    'firstname' => 'Jim',
                    'lastname' => 'Bloggs'
                ], 

            ]);

Pretty standard!

would I have to wrap each and every insert in a try catch? like this

try {
   DB::table('users')->insert(['member_id' => 11111111, 'firstname' => 'Joe', 'lastname' => 'Bloggs']);
} catch(Exception $e){
  //Die silently
}
try {
   DB::table('users')->insert(['member_id' => 22222222, 'firstname' => 'Jim', 'lastname' => 'Bloggs']);
} catch(Exception $e){
  //Die silently
}

Later on I might want to add extra rows to the same seeder without having to write a new one, and re run php artisan db:seed to only add my new rows.

Is this possible?

Upvotes: 4

Views: 12692

Answers (5)

Ben Sholdice
Ben Sholdice

Reputation: 407

As stokoe0990 stated, it is not advisable to run seeders in production. The Laravel Seeder was written as way to generate test data. Per the documentation "Laravel includes a simple method of seeding your database with test data using seed classes".

That said, The only way you can satisfy your question is to build the logic into your seed:

$users = array(
    ['member_id' => 11111111,'firstname' => 'Joe','lastname' => 'Bloggs'], 
    ['member_id' => 22222222,'firstname' => 'Jim','lastname' => 'Bloggs']
);

foreach ($users as $user) {
  if (\App\User::find($user['id'])) {
    DB::table('users')->insert($user);
  }
}

Upvotes: 3

Elisha Senoo
Elisha Senoo

Reputation: 3594

The best I recommend is to truncate (or delete all) the data in the table anytime you migrate. Try something like this:

//data in the table
DB::table('users')->delete(); //or use model like this: User::truncate();

DB::table('users')->insert([
                //Global Admin
                [
                    'member_id' => 11111111,
                    'firstname' => 'Joe',
                    'lastname' => 'Bloggs'
                ], 
                [
                    'member_id' => 22222222,
                    'firstname' => 'Jim',
                    'lastname' => 'Bloggs'
                ], 
            ]);

Then there will be no duplications when you run php artisan db:seed

Upvotes: 1

porloscerros Ψ
porloscerros Ψ

Reputation: 5088

You can achieve this by Eloquent firstOrCreate.

The firstOrCreate method will attempt to locate a database record using the given column / value pairs. If the model can not be found in the database, a record will be inserted with the attributes from the first parameter, along with those in the optional second parameter.

So, if you identify the user by member_id, you can do something like this:

    User::firstOrCreate(
        ['member_id' => 11111111],
        [
            'firstname' => 'anakin',
            'lastname' => 'skywalker',
            'password' => Hash::make('4nak1n')
        ]
    );

If you want to locate the record by 'member_id', 'firstname' and 'lastname' fields, something like this:

    User::firstOrCreate(
        [
            'member_id' => 11111111,
            'firstname' => 'anakin',
            'lastname' => 'skywalker'
        ],
        [
            'password' => Hash::make('4nak1n'),
        ]
    );

Upvotes: 8

zlatan
zlatan

Reputation: 3951

You can achieve that by using Eloquent updateOrInsert() method:

DB::table('users')->updateOrInsert('your_data');

Read more about it here.

Upvotes: 1

stokoe0990
stokoe0990

Reputation: 473

Seeding is only supposed to be used for testing, anyways.

Why don't you just execute php artisan migrate:fresh --seed?

This will refresh your database (deletes the tables) then runs all your migrations again and finally seeds the database again.

You should never be using seeders in production.

Just add the new data to your seeder, run migrate:fresh and re-seed :)

Upvotes: 3

Related Questions