diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index aedc7ab068325..f73e148a89b74 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -188,6 +188,12 @@ private static function throwInvalidArgumentException(string $message, array $tr } if (\PHP_VERSION_ID < 80000) { + if (preg_match('/^Typed property \S+::\$\S+ must be (\S+), (\S+) used$/', $message, $matches)) { + [, $expectedType, $actualType] = $matches; + + throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); + } + if (!str_starts_with($message, 'Argument ')) { return; } @@ -204,6 +210,11 @@ private static function throwInvalidArgumentException(string $message, array $tr if (preg_match('/^\S+::\S+\(\): Argument #\d+ \(\$\S+\) must be of type (\S+), (\S+) given/', $message, $matches)) { [, $expectedType, $actualType] = $matches; + throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); + } + if (preg_match('/^Cannot assign (\S+) to property \S+::\$\S+ of type (\S+)$/', $message, $matches)) { + [, $actualType, $expectedType] = $matches; + throw new InvalidArgumentException(sprintf('Expected argument of type "%s", "%s" given at property path "%s".', $expectedType, 'NULL' === $actualType ? 'null' : $actualType, $propertyPath), 0, $previous); } } diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypedProperty.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypedProperty.php new file mode 100644 index 0000000000000..1c4344c390d2d --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypedProperty.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +class TestClassTypedProperty +{ + public float $publicProperty; +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 5e9eca16e758e..6498fab2bfd90 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -29,6 +29,7 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassSetValue; +use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassTypedProperty; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassTypeErrorInsideCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestPublicPropertyDynamicallyCreated; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestPublicPropertyGetterOnObject; @@ -945,4 +946,16 @@ public function testGetDynamicPublicPropertyWithMagicGetterAllow() $object = new TestPublicPropertyGetterOnObjectMagicGet(); $this->assertSame($value, $this->propertyAccessor->getValue($object, $path)); } + + /** + * @requires PHP 7.4 + */ + public function testSetValueWrongTypeShouldThrowWrappedException() + { + $object = new TestClassTypedProperty(); + + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Expected argument of type "float", "string" given at property path "publicProperty"'); + $this->propertyAccessor->setValue($object, 'publicProperty', 'string'); + } }