Skip to content

Commit 58ea471

Browse files
Fix unsetting model castable attribute when cast to object (#56335) (#56343)
* Fix unsetting model castable attribute when cast to object Add test (#56335) * Change test name (#56335)
1 parent 6b11d5f commit 58ea471

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

src/Illuminate/Database/Eloquent/Model.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2463,7 +2463,12 @@ public function offsetSet($offset, $value): void
24632463
*/
24642464
public function offsetUnset($offset): void
24652465
{
2466-
unset($this->attributes[$offset], $this->relations[$offset], $this->attributeCastCache[$offset]);
2466+
unset(
2467+
$this->attributes[$offset],
2468+
$this->relations[$offset],
2469+
$this->attributeCastCache[$offset],
2470+
$this->classCastCache[$offset]
2471+
);
24672472
}
24682473

24692474
/**

tests/Database/DatabaseEloquentModelTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
use Illuminate\Support\InteractsWithTime;
5454
use Illuminate\Support\Stringable;
5555
use Illuminate\Support\Uri;
56+
use Illuminate\Tests\Database\stubs\TestCast;
57+
use Illuminate\Tests\Database\stubs\TestValueObject;
5658
use InvalidArgumentException;
5759
use LogicException;
5860
use Mockery as m;
@@ -2823,6 +2825,17 @@ public function testMergeCastsMergesCastsUsingArrays()
28232825
$this->assertEquals($model->getCasts()['bar'], 'MyClass:myArgumentA,myArgumentB');
28242826
}
28252827

2828+
public function testUnsetCastAttributes()
2829+
{
2830+
$model = new EloquentModelCastingStub;
2831+
$model->asToObjectCast = TestValueObject::make([
2832+
'myPropertyA' => 'A',
2833+
'myPropertyB' => 'B',
2834+
]);
2835+
unset($model->asToObjectCast);
2836+
$this->assertArrayNotHasKey('asToObjectCast', $model->getAttributes());
2837+
}
2838+
28262839
public function testUpdatingNonExistentModelFails()
28272840
{
28282841
$model = new EloquentModelStub;
@@ -3837,6 +3850,7 @@ protected function casts(): array
38373850
'asCustomEnumArrayObjectAttribute' => AsEnumArrayObject::of(StringStatus::class),
38383851
'singleElementInArrayAttribute' => [AsCollection::class],
38393852
'duplicatedAttribute' => 'int',
3853+
'asToObjectCast' => TestCast::class,
38403854
];
38413855
}
38423856

tests/Database/stubs/TestCast.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Database\stubs;
4+
5+
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class TestCast implements CastsAttributes
9+
{
10+
/**
11+
* @param Model $model
12+
* @param string $key
13+
* @param mixed $value
14+
* @param array $attributes
15+
* @return TestValueObject|null
16+
*/
17+
public function get(Model $model, string $key, mixed $value, array $attributes)
18+
{
19+
if (! json_validate($value)) {
20+
return null;
21+
}
22+
$value = json_decode($value, true);
23+
if (! is_array($value)) {
24+
return null;
25+
}
26+
27+
return TestValueObject::make($value);
28+
}
29+
30+
/**
31+
* @param Model $model
32+
* @param string $key
33+
* @param mixed $value
34+
* @param array $attributes
35+
* @return array
36+
*/
37+
public function set(Model $model, string $key, mixed $value, array $attributes)
38+
{
39+
if (! $value instanceof TestValueObject) {
40+
return [
41+
$key => null,
42+
];
43+
}
44+
45+
return [
46+
$key => json_encode($value->toArray()),
47+
];
48+
}
49+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Database\stubs;
4+
5+
class TestValueObject
6+
{
7+
private string $myPropertyA;
8+
private string $myPropertyB;
9+
10+
public static function make(?array $test): self
11+
{
12+
$self = new self;
13+
if (! empty($test['myPropertyA'])) {
14+
$self->myPropertyA = $test['myPropertyA'];
15+
}
16+
if (! empty($test['myPropertyB'])) {
17+
$self->myPropertyB = $test['myPropertyB'];
18+
}
19+
20+
return $self;
21+
}
22+
23+
public function toArray(): array
24+
{
25+
if (isset($this->myPropertyA)) {
26+
$result['myPropertyA'] = $this->myPropertyA;
27+
}
28+
if (isset($this->myPropertyB)) {
29+
$result['myPropertyB'] = $this->myPropertyB;
30+
}
31+
32+
return $result ?? [];
33+
}
34+
}

0 commit comments

Comments
 (0)