Skip to content

Commit b8f385b

Browse files
authored
[10.x] Do not apply global scopes when incrementing/decrementing an existing model (#47629)
* do not apply global scopes when incrementing or decrementing if model exists * fix DatabaseEloquentModelTest expectations for `newQueryWithoutScopes` * add test for increment/decrement existing model
1 parent 6b948d9 commit b8f385b

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -951,10 +951,8 @@ protected function decrement($column, $amount = 1, array $extra = [])
951951
*/
952952
protected function incrementOrDecrement($column, $amount, $extra, $method)
953953
{
954-
$query = $this->newQueryWithoutRelationships();
955-
956954
if (! $this->exists) {
957-
return $query->{$method}($column, $amount, $extra);
955+
return $this->newQueryWithoutRelationships()->{$method}($column, $amount, $extra);
958956
}
959957

960958
$this->{$column} = $this->isClassDeviable($column)
@@ -967,7 +965,7 @@ protected function incrementOrDecrement($column, $amount, $extra, $method)
967965
return false;
968966
}
969967

970-
return tap($this->setKeysForSaveQuery($query)->{$method}($column, $amount, $extra), function () use ($column) {
968+
return tap($this->setKeysForSaveQuery($this->newQueryWithoutScopes())->{$method}($column, $amount, $extra), function () use ($column) {
971969
$this->syncChanges();
972970

973971
$this->fireModelEvent('updated', false);

tests/Database/DatabaseEloquentModelTest.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,16 +2017,17 @@ public function testReplicateQuietlyCreatesANewModelInstanceWithSameAttributeVal
20172017

20182018
public function testIncrementOnExistingModelCallsQueryAndSetsAttribute()
20192019
{
2020-
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
2020+
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
20212021
$model->exists = true;
20222022
$model->id = 1;
20232023
$model->syncOriginalAttribute('id');
20242024
$model->foo = 2;
20252025

2026-
$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
2026+
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
20272027
$query->shouldReceive('where')->andReturn($query);
20282028
$query->shouldReceive('increment');
20292029

2030+
// hmm
20302031
$model->publicIncrement('foo', 1);
20312032
$this->assertFalse($model->isDirty());
20322033

@@ -2038,13 +2039,13 @@ public function testIncrementOnExistingModelCallsQueryAndSetsAttribute()
20382039

20392040
public function testIncrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAndIsQuiet()
20402041
{
2041-
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
2042+
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
20422043
$model->exists = true;
20432044
$model->id = 1;
20442045
$model->syncOriginalAttribute('id');
20452046
$model->foo = 2;
20462047

2047-
$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
2048+
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
20482049
$query->shouldReceive('where')->andReturn($query);
20492050
$query->shouldReceive('increment');
20502051

@@ -2065,13 +2066,13 @@ public function testIncrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAnd
20652066

20662067
public function testDecrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAndIsQuiet()
20672068
{
2068-
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
2069+
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
20692070
$model->exists = true;
20702071
$model->id = 1;
20712072
$model->syncOriginalAttribute('id');
20722073
$model->foo = 4;
20732074

2074-
$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
2075+
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
20752076
$query->shouldReceive('where')->andReturn($query);
20762077
$query->shouldReceive('decrement');
20772078

tests/Integration/Database/EloquentUpdateTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,24 @@ public function testIncrement()
118118
$this->assertEquals(1, $models[0]->counter);
119119
$this->assertEquals(0, $models[1]->counter);
120120
}
121+
122+
public function testIncrementOrDecrementIgnoresGlobalScopes()
123+
{
124+
/** @var TestUpdateModel3 $deletedModel */
125+
$deletedModel = tap(TestUpdateModel3::create([
126+
'counter' => 0,
127+
]), fn ($model) => $model->delete());
128+
129+
$deletedModel->increment('counter');
130+
131+
$this->assertEquals(1, $deletedModel->counter);
132+
133+
$deletedModel->fresh();
134+
$this->assertEquals(1, $deletedModel->counter);
135+
136+
$deletedModel->decrement('counter');
137+
$this->assertEquals(0, $deletedModel->fresh()->counter);
138+
}
121139
}
122140

123141
class TestUpdateModel1 extends Model

0 commit comments

Comments
 (0)