George Sharvadze
George Sharvadze

Reputation: 570

Laravel firstOrCreate with exceptions

let's say I have a following table: id | name | email | create_date | creator_id

When I'm using Laravel's firstOrCreate method it duplicates my records, because create_date and creator_id parameters are being changed on every call. Is there a way to disregard these fields while checking for an already existing record in DB?

Pseudo example might look like this: firstOrCreate(array('name'=>'test', 'email'=>'[email protected]'), $exceptionsArray('create_date', 'creator_id'))

Upvotes: 2

Views: 1669

Answers (2)

Amo
Amo

Reputation: 2944

The firstOrCreate() method accepts an array of attributes, and it's based on the existence of a record from those attributes that the record is either returned or created.

For instance:

| id | name | created_at           |
| 1  | Joe  | 2015-10-01 01:00:00  |
| 2  | Sam  | 2015-10-01 01:00:00  |
| 3  | Ali  | 2015-10-01 01:00:00  |
| 4  | Tom  | 2015-10-01 01:00:00  |

$user = User::firstOrCreate(['name' => 'Joe']);

// $user = record with id 1

This is an existing user, because firstOrFail() performs:

User::where('name', 'Joe')->first();

Next example:

$user = User::firstOrCreate(['name' => 'Joe', 'created_at' => '2015-10-01 01:00:00']);

// $user = record with id 1

This returns the user because under the hood the following query is performed:

User::where('name', 'Joe')->where('created_at', '2015-10-01 01:00:00')->first();

$user = User::firstOrCreate(['name' => 'Joe', 'created_at' => '2020-10-01 01:00:00']);

// $user = a brand new user, as the created_at time is different

What the firstOrCreate() method does is check to see if a record exists with the attributes you pass it.

So, taking the last example, the reason it created a new record is because it evaluated:

User::where('name', 'Joe')->where('created_at', '2020-10-01 01:00:00')->first();

Which will of course fail.

In short, when using firstOrCreate, don't pass a created_at attribute as this is always created dynamically, and in many cases you may not want to include a creator_id.

Upvotes: 3

Jirennor
Jirennor

Reputation: 1289

I don't know if this is an option for you but you could just use the exists() method on your query like this:

if (Model::where('name', '=', 'test')->where('email', '=', '[email protected]')->exists()) {
    // do something
} else {
    // add new record
}

Upvotes: 1

Related Questions