Skip to content

Commit 67a42dc

Browse files
committed
fix: toRawArray() converts DateTime objects to strings
Fixes #8302 When a date field is set on an Entity, __set() converts it to a Time object via mutateDate(). However, toRawArray() returned attributes directly without converting Time/DateTime objects back to strings. This fixes toRawArray() to return primitive types by converting DateTimeInterface objects to strings via __toString(). The underlying $this->attributes remain unchanged (still contain Time objects). toArray() behavior is preserved (still returns Time objects). Changes: - Entity::toRawArray(): DateTimeInterface objects converted to strings - Added test verifying: * toRawArray() returns strings for date fields * $this->attributes still contain Time objects * toArray() still returns Time objects (no regression) Ref: #8302
1 parent 2a1c348 commit 67a42dc

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

system/Entity/Entity.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recu
233233
public function toRawArray(bool $onlyChanged = false, bool $recursive = false): array
234234
{
235235
$convert = static function ($value) use (&$convert, $recursive) {
236+
// Always convert DateTime objects to string for raw output
237+
if ($value instanceof DateTimeInterface) {
238+
return (string) $value;
239+
}
240+
236241
if (! $recursive) {
237242
return $value;
238243
}
@@ -261,9 +266,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false):
261266

262267
// When returning everything
263268
if (! $onlyChanged) {
264-
return $recursive
265-
? array_map($convert, $this->attributes)
266-
: $this->attributes;
269+
return array_map($convert, $this->attributes);
267270
}
268271

269272
// When filtering by changed values only
@@ -335,7 +338,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false):
335338
}
336339

337340
// non-recursive changed value
338-
$return[$key] = $value;
341+
$return[$key] = $convert($value);
339342
}
340343

341344
return $return;

tests/system/Entity/EntityTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,41 @@ public function testDateMutationTimeToTime(): void
367367
$this->assertCloseEnoughString($dt->format('Y-m-d H:i:s'), $time->format('Y-m-d H:i:s'));
368368
}
369369

370+
public function testToRawArrayConvertsDateTimeToString(): void
371+
{
372+
$entity = new class () extends Entity {
373+
protected $attributes = [
374+
'created_at' => null,
375+
'updated_at' => null,
376+
];
377+
protected $original = [
378+
'created_at' => null,
379+
'updated_at' => null,
380+
];
381+
};
382+
383+
$entity->created_at = '2023-12-12 12:12:12';
384+
$entity->updated_at = '2023-12-13 13:13:13';
385+
386+
$raw = $entity->toRawArray();
387+
388+
// toRawArray() should return primitive types, not objects
389+
$this->assertIsString($raw['created_at']);
390+
$this->assertSame('2023-12-12 12:12:12', $raw['created_at']);
391+
$this->assertIsString($raw['updated_at']);
392+
$this->assertSame('2023-12-13 13:13:13', $raw['updated_at']);
393+
394+
// Attributes themselves should still contain Time objects
395+
$attrs = $this->getPrivateProperty($entity, 'attributes');
396+
$this->assertInstanceOf(Time::class, $attrs['created_at']);
397+
$this->assertInstanceOf(Time::class, $attrs['updated_at']);
398+
399+
// toArray() should still return Time objects (no regression)
400+
$array = $entity->toArray();
401+
$this->assertInstanceOf(Time::class, $array['created_at']);
402+
$this->assertInstanceOf(Time::class, $array['updated_at']);
403+
}
404+
370405
public function testCastInteger(): void
371406
{
372407
$entity = $this->getCastEntity();

0 commit comments

Comments
 (0)