-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Speed up ObjectNormalizer by introducing ObjectPropertyAccessorInterface #29405
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8238773
63ae16f
f33d764
223c1ea
ff2b450
7ec0174
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\PropertyAccess; | ||
|
||
/** | ||
* Writes and reads values to/from an object. | ||
* | ||
* @author Fabien Bourigault <bourigaultfabien@gmail.com> | ||
*/ | ||
interface ObjectPropertyAccessorInterface | ||
{ | ||
/** | ||
* Returns the object property value. | ||
* | ||
* @param object $object The object to get the value from | ||
* @param string $property The property to get the value from | ||
* | ||
* @return mixed The object property value | ||
* | ||
* @throws Exception\AccessException If the property does not exist | ||
*/ | ||
public function getPropertyValue($object, string $property); | ||
|
||
/** | ||
* Sets the object property value. | ||
* | ||
* @param object $object The object to modify | ||
* @param string $property The property to modify | ||
* @param mixed $value The value to set in the object property | ||
* | ||
* @throws Exception\InvalidArgumentException If the value is incompatible with property type | ||
* @throws Exception\AccessException If the property does not exist | ||
*/ | ||
public function setPropertyValue($object, string $property, $value); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,9 +12,11 @@ | |
namespace Symfony\Component\Serializer\Normalizer; | ||
|
||
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; | ||
use Symfony\Component\PropertyAccess\ObjectPropertyAccessorInterface; | ||
use Symfony\Component\PropertyAccess\PropertyAccess; | ||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; | ||
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; | ||
use Symfony\Component\Serializer\Exception\InvalidArgumentException; | ||
use Symfony\Component\Serializer\Exception\LogicException; | ||
use Symfony\Component\Serializer\Mapping\AttributeMetadata; | ||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; | ||
|
@@ -32,14 +34,22 @@ class ObjectNormalizer extends AbstractObjectNormalizer | |
|
||
private $discriminatorCache = []; | ||
|
||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) | ||
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null, ClassDiscriminatorResolverInterface $classDiscriminatorResolver = null, callable $objectClassResolver = null, array $defaultContext = []) | ||
{ | ||
if (!\class_exists(PropertyAccess::class)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this check be moved down a bit now as the PropertyAccess component is not necessarily needed anymore? |
||
throw new LogicException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.'); | ||
} | ||
|
||
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor, $classDiscriminatorResolver, $objectClassResolver, $defaultContext); | ||
|
||
if (null !== $propertyAccessor && !$propertyAccessor instanceof ObjectPropertyAccessorInterface && !$propertyAccessor instanceof PropertyAccessorInterface) { | ||
throw new InvalidArgumentException(sprintf('Argument 3 passed to "%s()" must be an instance of "%s" or an instance of "%s" or null, "%s" given.', __METHOD__, ObjectPropertyAccessorInterface::class, PropertyAccessorInterface::class, \gettype($propertyAccessor))); | ||
} | ||
|
||
if (null !== $propertyAccessor && !$propertyAccessor instanceof ObjectPropertyAccessorInterface) { | ||
@trigger_error(sprintf('Passing an instance of "%s" as the 3rd argument to "%s()" is deprecated since Symfony 4.3. Pass a "%s" instance instead.', PropertyAccessorInterface::class, __METHOD__, ObjectPropertyAccessorInterface::class), E_USER_DEPRECATED); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would reword this a bit to read like this: @trigger_error(sprintf('Passing a "%s" implementation as the 3rd argument to "%s()" that does not implement "%s" is deprecated since Symfony 4.3.', PropertyAccessorInterface::class, ObjectPropertyAccessorInterface::class, __METHOD__), E_USER_DEPRECATED); |
||
} | ||
|
||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); | ||
} | ||
|
||
|
@@ -121,7 +131,12 @@ protected function getAttributeValue($object, $attribute, $format = null, array | |
} | ||
} | ||
|
||
return $attribute === $this->discriminatorCache[$cacheKey] ? $this->classDiscriminatorResolver->getTypeForMappedObject($object) : $this->propertyAccessor->getValue($object, $attribute); | ||
return $attribute === $this->discriminatorCache[$cacheKey] | ||
? $this->classDiscriminatorResolver->getTypeForMappedObject($object) | ||
: ($this->propertyAccessor instanceof ObjectPropertyAccessorInterface | ||
? $this->propertyAccessor->getPropertyValue($object, $attribute) | ||
: $this->propertyAccessor->getValue($object, $attribute) | ||
); | ||
} | ||
|
||
/** | ||
|
@@ -130,7 +145,11 @@ protected function getAttributeValue($object, $attribute, $format = null, array | |
protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = []) | ||
{ | ||
try { | ||
$this->propertyAccessor->setValue($object, $attribute, $value); | ||
if ($this->propertyAccessor instanceof ObjectPropertyAccessorInterface) { | ||
$this->propertyAccessor->setPropertyValue($object, $attribute, $value); | ||
} else { | ||
$this->propertyAccessor->setValue($object, $attribute, $value); | ||
} | ||
} catch (NoSuchPropertyException $exception) { | ||
// Properties not found are ignored | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fbourigault i am not sure with this. But why is here no catch unlike in case of setPropertyValue ?
Both can throw and have invalid arguments...