Replies: 8 comments
-
There is one problem. Events. But in order for an update to happen, the row must be found in db via scopes from firstOrNew, no? Or the issue is on create rather than update? |
Beta Was this translation helpful? Give feedback.
-
Are you using composed primary keys or composed unique constraints instead of primary id? If yes then you can define your model to use composed primary keys and the save will have both conditions, id and team_id. |
Beta Was this translation helpful? Give feedback.
-
You're right that using a composite primary key like However, Eloquent doesn't natively support composite primary keys. Even if defined in the database, Laravel will still only use To make this work properly, you'd need to override protected function setKeysForSaveQuery($query)
{
return $query->where('id', $this->id)
->where('team_id', $this->team_id);
} So yes, it’s technically possible to fix the issue with custom model logic – but the point of this bug report is that the current default behavior in updateOrCreate() is misleading and unsafe in multi-tenant contexts unless developers are aware of this Laravel quirk. |
Beta Was this translation helpful? Give feedback.
-
You're right that mass updates skip model events — but in this case, The The core problem is that during So even if you retrieved the model within the proper tenant scope, the subsequent This isn't a mass update issue — it's a scope consistency issue. |
Beta Was this translation helpful? Give feedback.
-
@Sairahcaz This is intended behavior. The save saves the model in db by its primary key (id) which should be unique even for your case. This should not include the builder scopes. Eloquent can be extended to support composite PKs. Demo model with composed PK: Demo service with composed PK: This is your solution. But if id is unique there is no point anyway on doing this. EDIT. |
Beta Was this translation helpful? Give feedback.
-
Thanks! I fully agree that Laravel's But this issue is not about wanting composite primary keys per se — it's about the inconsistency of That means even if I retrieved a model within the tenant scope, Laravel can later update it outside that scope, unless I override Whether or not And just to clarify, Laravel explicitly states in the docs that composite primary keys are not supported:
So while it's technically possible to work around this with custom logic or third-party packages, it's not something Laravel supports or encourages natively. That's why I opened this issue — because the current
That disconnect is easy to miss, and potentially dangerous in scoped environments. Thanks again for the discussion and links — but I still believe this behavior should at least be documented or made more consistent. |
Beta Was this translation helpful? Give feedback.
-
Documented yes. Thank you. |
Beta Was this translation helpful? Give feedback.
-
@Sairahcaz |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Laravel Version
11.43.2
PHP Version
8.2.28
Database Driver & Version
mysql Ver 8.0.36 for macos14 on arm64 (MySQL Community Server - GPL)
Description
The
updateOrCreate()
method behaves inconsistently with regard to global scopes in Laravel:firstOrNew()
, global scopes are applied.$model->save()
, the resultingUPDATE
query does not include any global scope constraints.This inconsistency is particularly problematic in multi-tenant applications where global scopes are used to enforce tenant isolation (e.g.
team_id
,organization_id
).Expected Behavior
The
UPDATE
query should respect global scopes, just like theSELECT
query does.Thanks again for all the amazing work on Laravel!
Steps To Reproduce
1. Define a global scope on
team_id
:2. Call updateOrCreate() on an existing record:
3. Observe the SQL queries:
Beta Was this translation helpful? Give feedback.
All reactions