-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Closed
Description
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:
- When finding the model via
firstOrNew(), global scopes are applied. - When updating the existing model via
$model->save(), the resultingUPDATEquery 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 the SELECT query does.
Thanks again for all the amazing work on Laravel!
Steps To Reproduce
1. Define a global scope on team_id:
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
protected static function booted(): void
{
static::addGlobalScope('team', function (Builder $builder) {
if (auth()->check()) {
$builder->where('team_id', auth()->user()->team_id);
}
});
}
}2. Call updateOrCreate() on an existing record:
Flight::updateOrCreate(
['id' => 123], // Existing record with team_id = 1
['status' => 'delayed']
);3. Observe the SQL queries:
-- SELECT query (correctly scoped):
SELECT * FROM flights WHERE id = 123 AND team_id = 1 LIMIT 1;
-- UPDATE query (missing scope!):
UPDATE flights SET status = 'delayed' WHERE id = 123;
-- ⚠️ Missing team_id = 1 in the WHERE clauseMetadata
Metadata
Assignees
Labels
No labels