diff --git a/src/Attributes/Field.php b/src/Attributes/Field.php index e4e764e..b949a11 100644 --- a/src/Attributes/Field.php +++ b/src/Attributes/Field.php @@ -414,6 +414,18 @@ public function validate(mixed $value): bool }; } + /** + * We're returning early under this conditions due to the fact that a SequenceField + * instance call to `validate` with a null value would throw an exception. + * + * Unfortunately at this moment, only the value can be passed to the `validate`, + * meaning we cannot check `$this->nullable`, which would allow us to have this check inside the `validate` + * method of the SequenceField instance. + */ + if ($this->phpType === 'array' && $this->nullable && $value === null && $valid) { + return true; + } + // The value validates if it passes the simple check above, // plus the typeField check, if any. return $valid && ($this->typeField?->validate($value) ?? true); diff --git a/tests/Records/NullablePointList.php b/tests/Records/NullablePointList.php new file mode 100644 index 0000000..431f32d --- /dev/null +++ b/tests/Records/NullablePointList.php @@ -0,0 +1,19 @@ +|null $points + */ + public function __construct( + #[SequenceField(arrayType: Point::class)] + public array|null $points = null, + ) { + } +} diff --git a/tests/Records/NullablePointListWithoutConstructor.php b/tests/Records/NullablePointListWithoutConstructor.php new file mode 100644 index 0000000..7ea36e3 --- /dev/null +++ b/tests/Records/NullablePointListWithoutConstructor.php @@ -0,0 +1,24 @@ + [ + 'data' => new NullablePointList(), + ]; + + $reflected = new ReflectionClass(NullablePointListWithoutConstructor::class); + $instance = $reflected->newInstanceWithoutConstructor(); + $reflected->getProperty('points')->setValue($instance, null); + yield 'nullable_list_without_constructor' => [ + 'data' => $instance, + ]; } public static function value_object_flatten_examples(): \Generator