Skip to content

Commit

Permalink
[10.x] Allow object caching to be disabled for custom class casters (#…
Browse files Browse the repository at this point in the history
…47423)

* Allow caching to be disabled for class casters

* formatting

---------

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
calebdw and taylorotwell authored Jun 18, 2023
1 parent 42173c8 commit 783a000
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -803,16 +803,20 @@ protected function castAttribute($key, $value)
*/
protected function getClassCastableAttributeValue($key, $value)
{
if (isset($this->classCastCache[$key])) {
$caster = $this->resolveCasterClass($key);

$objectCachingDisabled = $caster->withoutObjectCaching ?? false;

if (isset($this->classCastCache[$key]) && ! $objectCachingDisabled) {
return $this->classCastCache[$key];
} else {
$caster = $this->resolveCasterClass($key);

$value = $caster instanceof CastsInboundAttributes
? $value
: $caster->get($this, $key, $value, $this->attributes);

if ($caster instanceof CastsInboundAttributes || ! is_object($value)) {
if ($caster instanceof CastsInboundAttributes ||
! is_object($value) ||
$objectCachingDisabled) {
unset($this->classCastCache[$key]);
} else {
$this->classCastCache[$key] = $value;
Expand Down Expand Up @@ -1134,7 +1138,9 @@ protected function setClassCastableAttribute($key, $value)
))
);

if ($caster instanceof CastsInboundAttributes || ! is_object($value)) {
if ($caster instanceof CastsInboundAttributes ||
! is_object($value) ||
($caster->withoutObjectCaching ?? false)) {
unset($this->classCastCache[$key]);
} else {
$this->classCastCache[$key] = $value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ public function testBasicCustomCasting()
$model = new TestEloquentModelWithCustomCast;
$model->birthday_at = now();
$this->assertIsString($model->toArray()['birthday_at']);

$model = new TestEloquentModelWithCustomCast;
$now = now()->toImmutable();
$model->anniversary_on_with_object_caching = $now;
$model->anniversary_on_without_object_caching = $now;
$this->assertSame($now, $model->anniversary_on_with_object_caching);
$this->assertSame('UTC', $model->anniversary_on_with_object_caching->format('e'));
$this->assertNotSame($now, $model->anniversary_on_without_object_caching);
$this->assertNotSame('UTC', $model->anniversary_on_without_object_caching->format('e'));
}

public function testGetOriginalWithCastValueObjects()
Expand Down Expand Up @@ -299,6 +308,8 @@ class TestEloquentModelWithCustomCast extends Model
'value_object_caster_with_caster_instance' => ValueObjectWithCasterInstance::class,
'undefined_cast_column' => UndefinedCast::class,
'birthday_at' => DateObjectCaster::class,
'anniversary_on_with_object_caching' => DateTimezoneCasterWithObjectCaching::class.':America/New_York',
'anniversary_on_without_object_caching' => DateTimezoneCasterWithoutObjectCaching::class.':America/New_York',
];
}

Expand Down Expand Up @@ -584,3 +595,25 @@ public function set($model, $key, $value, $attributes)
return $value->format('Y-m-d');
}
}

class DateTimezoneCasterWithObjectCaching implements CastsAttributes
{
public function __construct(private string $timezone = 'UTC')
{
}

public function get($model, $key, $value, $attributes)
{
return Carbon::parse($value, $this->timezone);
}

public function set($model, $key, $value, $attributes)
{
return $value->timezone($this->timezone)->format('Y-m-d');
}
}

class DateTimezoneCasterWithoutObjectCaching extends DateTimezoneCasterWithObjectCaching
{
public bool $withoutObjectCaching = true;
}

0 comments on commit 783a000

Please sign in to comment.