From c8ef7772b8b475b200a7ad5def012a458161728f Mon Sep 17 00:00:00 2001 From: Ilya Orlov Date: Wed, 6 Nov 2024 15:31:25 +0500 Subject: [PATCH 1/2] Fix for readonly properties that declared in parent --- src/Serializers/Native.php | 4 ++++ tests/SerializerPhp81Test.php | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Serializers/Native.php b/src/Serializers/Native.php index 59a1bc6c..73254902 100644 --- a/src/Serializers/Native.php +++ b/src/Serializers/Native.php @@ -504,6 +504,10 @@ protected function mapByReference(&$data) continue; } + if (PHP_VERSION >= 8.1 && $property->isReadOnly() && $property->class !== $reflection->name) { + continue; + } + $value = $property->getValue($instance); if (is_array($value) || is_object($value)) { diff --git a/tests/SerializerPhp81Test.php b/tests/SerializerPhp81Test.php index 41c6a6ed..474e10a4 100644 --- a/tests/SerializerPhp81Test.php +++ b/tests/SerializerPhp81Test.php @@ -183,6 +183,20 @@ enum SerializerScopedBackedEnum: string { ); })->with('serializers'); +test('readonly properties declared in parent', function () { + $controller = new SerializerPhp81ControllerChild(); + + $f = static function () use ($controller) { + return $controller; + }; + + $f = s($f); + + expect($f()->service)->toBeInstanceOf( + SerializerPhp81Service::class, + ); +})->with('serializers'); + test('first-class callable with closures', function () { $f = function ($value) { return $value; @@ -589,6 +603,8 @@ class SerializerPhp81Service implements SerializerPhp81HasId, SerializerPhp81Has final public const X = 'foo'; } +class SerializerPhp81ControllerChild extends SerializerPhp81Controller {} + class SerializerPhp81Controller { public function __construct( From 63c06cd03a8d482139aa761724b1531d8c44ae99 Mon Sep 17 00:00:00 2001 From: Ilya Orlov Date: Thu, 14 Nov 2024 14:00:14 +0500 Subject: [PATCH 2/2] More tests for readonly properties that declared in parent --- tests/SerializerPhp81Test.php | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/SerializerPhp81Test.php b/tests/SerializerPhp81Test.php index 474e10a4..bd356131 100644 --- a/tests/SerializerPhp81Test.php +++ b/tests/SerializerPhp81Test.php @@ -184,17 +184,25 @@ enum SerializerScopedBackedEnum: string { })->with('serializers'); test('readonly properties declared in parent', function () { - $controller = new SerializerPhp81ControllerChild(); + $childWithDefaultValue = new SerializerPhp81Child(); - $f = static function () use ($controller) { - return $controller; + $f = static function () use ($childWithDefaultValue) { + return $childWithDefaultValue; }; $f = s($f); - expect($f()->service)->toBeInstanceOf( - SerializerPhp81Service::class, - ); + expect($f()->property)->toBe(1); + + $child = new SerializerPhp81Child(100); + + $f = static function () use ($child) { + return $child; + }; + + $f = s($f); + + expect($f()->property)->toBe(100); })->with('serializers'); test('first-class callable with closures', function () { @@ -598,13 +606,20 @@ enum SerializerScopedBackedEnum: string { interface SerializerPhp81HasId {} interface SerializerPhp81HasName {} +class SerializerPhp81Child extends SerializerPhp81Parent {} + +class SerializerPhp81Parent +{ + public function __construct( + public readonly int $property = 1, + ) {} +} + class SerializerPhp81Service implements SerializerPhp81HasId, SerializerPhp81HasName { final public const X = 'foo'; } -class SerializerPhp81ControllerChild extends SerializerPhp81Controller {} - class SerializerPhp81Controller { public function __construct(