From 5655dfcb90c1ae97aabe9c2c1fccc35d8a424724 Mon Sep 17 00:00:00 2001 From: Guram Vashakidze Date: Sun, 20 Jul 2025 13:28:26 +0300 Subject: [PATCH 1/2] Fix unsetting model castable attribute when cast to object Add test (#56335) --- src/Illuminate/Database/Eloquent/Model.php | 7 ++- tests/Database/DatabaseEloquentModelTest.php | 14 ++++++ tests/Database/stubs/TestCast.php | 49 ++++++++++++++++++++ tests/Database/stubs/TestValueObject.php | 34 ++++++++++++++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/Database/stubs/TestCast.php create mode 100644 tests/Database/stubs/TestValueObject.php diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 85049922dcb1..f9d1ba0d3b5e 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -2463,7 +2463,12 @@ public function offsetSet($offset, $value): void */ public function offsetUnset($offset): void { - unset($this->attributes[$offset], $this->relations[$offset], $this->attributeCastCache[$offset]); + unset( + $this->attributes[$offset], + $this->relations[$offset], + $this->attributeCastCache[$offset], + $this->classCastCache[$offset] + ); } /** diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index fb24946d429c..3ffb9a1428a3 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -53,6 +53,8 @@ use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Stringable; use Illuminate\Support\Uri; +use Illuminate\Tests\Database\stubs\TestCast; +use Illuminate\Tests\Database\stubs\TestValueObject; use InvalidArgumentException; use LogicException; use Mockery as m; @@ -2823,6 +2825,17 @@ public function testMergeCastsMergesCastsUsingArrays() $this->assertEquals($model->getCasts()['bar'], 'MyClass:myArgumentA,myArgumentB'); } + public function testUnsetAttributes() + { + $model = new EloquentModelCastingStub; + $model->asToObjectCast = TestValueObject::make([ + 'myPropertyA' => 'A', + 'myPropertyB' => 'B', + ]); + unset($model->asToObjectCast); + $this->assertArrayNotHasKey('asToObjectCast', $model->getAttributes()); + } + public function testUpdatingNonExistentModelFails() { $model = new EloquentModelStub; @@ -3837,6 +3850,7 @@ protected function casts(): array 'asCustomEnumArrayObjectAttribute' => AsEnumArrayObject::of(StringStatus::class), 'singleElementInArrayAttribute' => [AsCollection::class], 'duplicatedAttribute' => 'int', + 'asToObjectCast' => TestCast::class, ]; } diff --git a/tests/Database/stubs/TestCast.php b/tests/Database/stubs/TestCast.php new file mode 100644 index 000000000000..4127bcd42598 --- /dev/null +++ b/tests/Database/stubs/TestCast.php @@ -0,0 +1,49 @@ + null, + ]; + } + + return [ + $key => json_encode($value->toArray()), + ]; + } +} diff --git a/tests/Database/stubs/TestValueObject.php b/tests/Database/stubs/TestValueObject.php new file mode 100644 index 000000000000..a9e67727e107 --- /dev/null +++ b/tests/Database/stubs/TestValueObject.php @@ -0,0 +1,34 @@ +myPropertyA = $test['myPropertyA']; + } + if (! empty($test['myPropertyB'])) { + $self->myPropertyB = $test['myPropertyB']; + } + + return $self; + } + + public function toArray(): array + { + if (isset($this->myPropertyA)) { + $result['myPropertyA'] = $this->myPropertyA; + } + if (isset($this->myPropertyB)) { + $result['myPropertyB'] = $this->myPropertyB; + } + + return $result ?? []; + } +} From 394a938147395a6cfc348ab906f49b84f71e9f3e Mon Sep 17 00:00:00 2001 From: Guram Vashakidze Date: Sun, 20 Jul 2025 13:34:29 +0300 Subject: [PATCH 2/2] Change test name (#56335) --- tests/Database/DatabaseEloquentModelTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 3ffb9a1428a3..a085d3ea31e4 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -2825,7 +2825,7 @@ public function testMergeCastsMergesCastsUsingArrays() $this->assertEquals($model->getCasts()['bar'], 'MyClass:myArgumentA,myArgumentB'); } - public function testUnsetAttributes() + public function testUnsetCastAttributes() { $model = new EloquentModelCastingStub; $model->asToObjectCast = TestValueObject::make([