diff --git a/system/Entity/Entity.php b/system/Entity/Entity.php index e3733bd0fc02..0d8bccbc3cd1 100644 --- a/system/Entity/Entity.php +++ b/system/Entity/Entity.php @@ -233,6 +233,11 @@ public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recu public function toRawArray(bool $onlyChanged = false, bool $recursive = false): array { $convert = static function ($value) use (&$convert, $recursive) { + // Always convert DateTime objects to string for raw output + if ($value instanceof DateTimeInterface) { + return (string) $value; + } + if (! $recursive) { return $value; } @@ -261,9 +266,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false): // When returning everything if (! $onlyChanged) { - return $recursive - ? array_map($convert, $this->attributes) - : $this->attributes; + return array_map($convert, $this->attributes); } // When filtering by changed values only @@ -335,7 +338,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false): } // non-recursive changed value - $return[$key] = $value; + $return[$key] = $convert($value); } return $return; diff --git a/tests/system/Entity/EntityTest.php b/tests/system/Entity/EntityTest.php index 52d1de2f5a8b..c13bf1453aa9 100644 --- a/tests/system/Entity/EntityTest.php +++ b/tests/system/Entity/EntityTest.php @@ -367,6 +367,41 @@ public function testDateMutationTimeToTime(): void $this->assertCloseEnoughString($dt->format('Y-m-d H:i:s'), $time->format('Y-m-d H:i:s')); } + public function testToRawArrayConvertsDateTimeToString(): void + { + $entity = new class () extends Entity { + protected $attributes = [ + 'created_at' => null, + 'updated_at' => null, + ]; + protected $original = [ + 'created_at' => null, + 'updated_at' => null, + ]; + }; + + $entity->created_at = '2023-12-12 12:12:12'; + $entity->updated_at = '2023-12-13 13:13:13'; + + $raw = $entity->toRawArray(); + + // toRawArray() should return primitive types, not objects + $this->assertIsString($raw['created_at']); + $this->assertSame('2023-12-12 12:12:12', $raw['created_at']); + $this->assertIsString($raw['updated_at']); + $this->assertSame('2023-12-13 13:13:13', $raw['updated_at']); + + // Attributes themselves should still contain Time objects + $attrs = $this->getPrivateProperty($entity, 'attributes'); + $this->assertInstanceOf(Time::class, $attrs['created_at']); + $this->assertInstanceOf(Time::class, $attrs['updated_at']); + + // toArray() should still return Time objects (no regression) + $array = $entity->toArray(); + $this->assertInstanceOf(Time::class, $array['created_at']); + $this->assertInstanceOf(Time::class, $array['updated_at']); + } + public function testCastInteger(): void { $entity = $this->getCastEntity();