diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
index aa0a2fc921853..a9d7d0a63bf6c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -249,6 +249,7 @@ protected static function getBundleDefaultConfig()
'property_access' => [
'magic_call' => false,
'throw_exception_on_invalid_index' => false,
+ 'throw_exception_on_invalid_property_path' => true,
],
'property_info' => [
'enabled' => !class_exists(FullStack::class),
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php
index b5b060c1baa43..8f431f8735d89 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/property_accessor.php
@@ -4,5 +4,6 @@
'property_access' => [
'magic_call' => true,
'throw_exception_on_invalid_index' => true,
+ 'throw_exception_on_invalid_property_path' => false,
],
]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml
index 95ddef8288e38..07e33ae3e8d96 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/property_accessor.xml
@@ -7,6 +7,6 @@
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml
index b5fd2718ab112..ea527c9821116 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/property_accessor.yml
@@ -2,3 +2,4 @@ framework:
property_access:
magic_call: true
throw_exception_on_invalid_index: true
+ throw_exception_on_invalid_property_path: false
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index acc7fbad156e7..1b8a785a303db 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -80,6 +80,7 @@ public function testPropertyAccessWithDefaultValue()
$def = $container->getDefinition('property_accessor');
$this->assertFalse($def->getArgument(0));
$this->assertFalse($def->getArgument(1));
+ $this->assertTrue($def->getArgument(3));
}
public function testPropertyAccessWithOverriddenValues()
@@ -88,6 +89,7 @@ public function testPropertyAccessWithOverriddenValues()
$def = $container->getDefinition('property_accessor');
$this->assertTrue($def->getArgument(0));
$this->assertTrue($def->getArgument(1));
+ $this->assertFalse($def->getArgument(3));
}
public function testPropertyAccessCache()
diff --git a/src/Symfony/Component/PropertyAccess/CHANGELOG.md b/src/Symfony/Component/PropertyAccess/CHANGELOG.md
index 970f3545b5702..0a012bb47620d 100644
--- a/src/Symfony/Component/PropertyAccess/CHANGELOG.md
+++ b/src/Symfony/Component/PropertyAccess/CHANGELOG.md
@@ -1,6 +1,13 @@
CHANGELOG
=========
+4.3.0
+-----
+
+* added a `$throwExceptionOnInvalidPropertyPath` argument to the PropertyAccessor constructor.
+* added `enableExceptionOnInvalidPropertyPath()`, `disableExceptionOnInvalidPropertyPath()` and
+ `isExceptionOnInvalidPropertyPath()` methods to `PropertyAccessorBuilder`
+
4.0.0
-----
diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
index db9c6b84652ea..891cc5e75ea46 100644
--- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
@@ -56,6 +56,7 @@ class PropertyAccessor implements PropertyAccessorInterface
*/
private $magicCall;
private $ignoreInvalidIndices;
+ private $ignoreInvalidProperty;
/**
* @var CacheItemPoolInterface
@@ -70,11 +71,12 @@ class PropertyAccessor implements PropertyAccessorInterface
* Should not be used by application code. Use
* {@link PropertyAccess::createPropertyAccessor()} instead.
*/
- public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null)
+ public function __construct(bool $magicCall = false, bool $throwExceptionOnInvalidIndex = false, CacheItemPoolInterface $cacheItemPool = null, bool $throwExceptionOnInvalidPropertyPath = true)
{
$this->magicCall = $magicCall;
$this->ignoreInvalidIndices = !$throwExceptionOnInvalidIndex;
$this->cacheItemPool = $cacheItemPool instanceof NullAdapter ? null : $cacheItemPool; // Replace the NullAdapter by the null value
+ $this->ignoreInvalidProperty = !$throwExceptionOnInvalidPropertyPath;
}
/**
@@ -87,7 +89,7 @@ public function getValue($objectOrArray, $propertyPath)
];
if (\is_object($objectOrArray) && false === strpbrk((string) $propertyPath, '.[')) {
- return $this->readProperty($zval, $propertyPath)[self::VALUE];
+ return $this->readProperty($zval, $propertyPath, $this->ignoreInvalidProperty)[self::VALUE];
}
$propertyPath = $this->getPropertyPath($propertyPath);
@@ -313,7 +315,7 @@ private function readPropertiesUntil($zval, PropertyPathInterface $propertyPath,
$zval = $this->readIndex($zval, $property);
} else {
- $zval = $this->readProperty($zval, $property);
+ $zval = $this->readProperty($zval, $property, $this->ignoreInvalidProperty);
}
// the final value of the path must not be validated
@@ -372,14 +374,15 @@ private function readIndex($zval, $index)
/**
* Reads the a property from an object.
*
- * @param array $zval The array containing the object to read from
- * @param string $property The property to read
+ * @param array $zval The array containing the object to read from
+ * @param string $property The property to read
+ * @param bool $ignoreInvalidProperty Whether to ignore invalid property or throw an exception
*
* @return array The array containing the value of the property
*
- * @throws NoSuchPropertyException if the property does not exist or is not public
+ * @throws NoSuchPropertyException If $ignoreInvalidProperty is false and the property does not exist or is not public
*/
- private function readProperty($zval, $property)
+ private function readProperty($zval, $property, bool $ignoreInvalidProperty = false)
{
if (!\is_object($zval[self::VALUE])) {
throw new NoSuchPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you intended to write the property path as "[%1$s]" instead.', $property));
@@ -411,7 +414,7 @@ private function readProperty($zval, $property)
} elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) {
// we call the getter and hope the __call do the job
$result[self::VALUE] = $object->{$access[self::ACCESS_NAME]}();
- } else {
+ } elseif (!$ignoreInvalidProperty) {
throw new NoSuchPropertyException($access[self::ACCESS_NAME]);
}
diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php
index 1db6a1dba23ed..a300bdc6f5c36 100644
--- a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php
+++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php
@@ -22,6 +22,7 @@ class PropertyAccessorBuilder
{
private $magicCall = false;
private $throwExceptionOnInvalidIndex = false;
+ private $throwExceptionOnInvalidPropertyPath = true;
/**
* @var CacheItemPoolInterface|null
@@ -97,6 +98,43 @@ public function isExceptionOnInvalidIndexEnabled()
return $this->throwExceptionOnInvalidIndex;
}
+ /**
+ * Enables exceptions when reading a non-existing property.
+ *
+ * This has no influence on writing non-existing indices with PropertyAccessorInterface::setValue()
+ * which are always created on-the-fly.
+ *
+ * @return $this
+ */
+ public function enableExceptionOnInvalidPropertyPath()
+ {
+ $this->throwExceptionOnInvalidPropertyPath = true;
+
+ return $this;
+ }
+
+ /**
+ * Disables exceptions when reading a non-existing index.
+ *
+ * Instead, null is returned when calling PropertyAccessorInterface::getValue() on a non-existing index.
+ *
+ * @return $this
+ */
+ public function disableExceptionOnInvalidPropertyPath()
+ {
+ $this->throwExceptionOnInvalidPropertyPath = false;
+
+ return $this;
+ }
+
+ /**
+ * @return bool whether an exception is thrown or null is returned when reading a non-existing property
+ */
+ public function isExceptionOnInvalidPropertyPath()
+ {
+ return $this->throwExceptionOnInvalidPropertyPath;
+ }
+
/**
* Sets a cache system.
*
@@ -128,6 +166,6 @@ public function getCacheItemPool()
*/
public function getPropertyAccessor()
{
- return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool);
+ return new PropertyAccessor($this->magicCall, $this->throwExceptionOnInvalidIndex, $this->cacheItemPool, $this->throwExceptionOnInvalidPropertyPath);
}
}
diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
index 2a7dd8a83192b..d0cbccf1ec63c 100644
--- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
@@ -14,6 +14,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
+use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
@@ -100,6 +101,16 @@ public function testGetValueThrowsExceptionIfPropertyNotFound($objectOrArray, $p
$this->propertyAccessor->getValue($objectOrArray, $path);
}
+ /**
+ * @dataProvider getPathsWithMissingProperty
+ */
+ public function testGetValueReturnsNullIfPropertyNotFoundAndExceptionIsDisabled($objectOrArray, $path)
+ {
+ $this->propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()->disableExceptionOnInvalidPropertyPath()->getPropertyAccessor();
+
+ $this->assertNull($this->propertyAccessor->getValue($objectOrArray, $path), $path);
+ }
+
/**
* @dataProvider getPathsWithMissingIndex
*/
@@ -618,6 +629,25 @@ public function testAnonymousClassRead()
$this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo'));
}
+ /**
+ * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException
+ */
+ public function testAnonymousClassReadThrowExceptionOnInvalidPropertyPath()
+ {
+ $obj = $this->generateAnonymousClass('bar');
+
+ $this->propertyAccessor->getValue($obj, 'invalid_property');
+ }
+
+ public function testAnonymousClassReadReturnsNullOnInvalidPropertyWithDisabledException()
+ {
+ $obj = $this->generateAnonymousClass('bar');
+
+ $this->propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()->disableExceptionOnInvalidPropertyPath()->getPropertyAccessor();
+
+ $this->assertNull($this->propertyAccessor->getValue($obj, 'invalid_property'));
+ }
+
public function testAnonymousClassWrite()
{
$value = 'bar';
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy