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

erikgyepes's avatar

Eloquent updateOrCreate() overwrites all rows - trying to understand it

Hey guys.

I'm having problem understanding the updateOrCreate Eloquent method.

I have a simple DB where I'm saving information from API and running every x minutes.

What I need to to is to do an INSERT if the row doesn't exists in the DB or otherwise just do an UPDATE and update the changed data.

How can we achieve this functionality in Laravel?

Here is what I have right now, but what happens it rewrites the same data across all rows.

Not sure if I understand it correctly.

I'm basically passing in a "condition" ie. fields that needs to be checked against if they are unique - campaign_id+variation_id should be unique. (it's backed by UNIQUE key in MySQL) and my data array:

$data = [
    'campaign_id' => $variation['campaign_id'],
    'variation_id' => $variation['variation_id'],
    'name' => $variation['name'],
    'description' => $variation['description'],
];

MyModel::updateOrCreate( ['campaign_id' => $variation['campaign_id'], 'variation_id' => 
$variation['variation_id'] ], $data);

It seems to work with the updateOrInsert which is a Query Builder method, but I wanted to achieve this with Eloquent, thought it will be easy. Plus Query Builder doesn't fill the timestamps for me.

Thanks for any hints!

0 likes
8 replies
tykus's avatar

it rewrites the same data across all rows

So does campaign_id and variation_id combination exist across multiple rows? What do you mean all rows?

If you source-dive updateOrCreate you should see that it uses firstOrNew to find the first instance matching the attributes given in the first array (or create a new instance with those same attributes); then fills that instance with the values in the second array ($data) and persists this. There is no reason for more than one row to be updated...

erikgyepes's avatar

The same campaign_id or variation_id can be in other row/record, but the same combination cannot.

In my case it's updating the same "name" and "description" to all rows.

Ie. it should be: campaign_id,variation_id,name,description

1,1,"Foo","Bar"
1,2,"Baz","Daz"
2,1,"Xxx","Yyy"

But what I get is:

1,1,"Foo","Bar"
1,2,"Foo","Bar"
2,1,"Foo","Bar"

It should do a simple WHERE (campaign_id = ? AND variation_id = ?) query, but it seems to be omitting one of the condition and that's why the data are overwritten.

tykus's avatar

Well, that's precisely what firstOrNew does

$instance = $this->where($attributes)->first()

$attributes is the first array passed into updateOrCreate.

erikgyepes's avatar

I see. So what do you suggest as a solution if I want to take the Eloquent way?

tykus's avatar

My point is that it should work as expected. I would be debugging why everything is being updated, e.g. if there is something overriding the default implementation of the updateOrCreate (or other methods). You can also check which queries are being executed (and where) using Laravel Debugbar.

1 like
robrogers3's avatar

Yep I agree with @tykus you need some logging or debugging. Something cooky is happening. Lets see what sql it's pumping out, and go from there.

erikgyepes's avatar

SQL is along these lines:

select * from variations where (campaign_id = ? and variation_id = ?) limit 1" "update variations set name = ?, description = ?, updated_at = ? where campaign_id = ? 

.... it's omitting the AND variation_id = ? condition. No idea why.

Please or to participate in this conversation.