function AbstractNormalizer::instantiateObject
Instantiates an object using constructor parameters when needed.
This method also allows to denormalize data into an existing object if it is present in the context with the object_to_populate. This object is removed from the context before being returned to avoid side effects when recursively normalizing an object graph.
Throws
MissingConstructorArgumentsException
2 calls to AbstractNormalizer::instantiateObject()
- AbstractObjectNormalizer::instantiateObject in vendor/
symfony/ serializer/ Normalizer/ AbstractObjectNormalizer.php - Instantiates an object using constructor parameters when needed.
- AbstractObjectNormalizer::instantiateObject in vendor/
symfony/ serializer/ Normalizer/ AbstractObjectNormalizer.php - Instantiates an object using constructor parameters when needed.
1 method overrides AbstractNormalizer::instantiateObject()
- AbstractObjectNormalizer::instantiateObject in vendor/
symfony/ serializer/ Normalizer/ AbstractObjectNormalizer.php - Instantiates an object using constructor parameters when needed.
File
-
vendor/
symfony/ serializer/ Normalizer/ AbstractNormalizer.php, line 312
Class
- AbstractNormalizer
- Normalizer implementation.
Namespace
Symfony\Component\Serializer\NormalizerCode
protected function instantiateObject(array &$data, string $class, array &$context, \ReflectionClass $reflectionClass, array|bool $allowedAttributes, ?string $format = null) : object {
if (null !== ($object = $this->extractObjectToPopulate($class, $context, self::OBJECT_TO_POPULATE))) {
unset($context[self::OBJECT_TO_POPULATE]);
return $object;
}
// clean up even if no match
unset($context[static::OBJECT_TO_POPULATE]);
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
if ($constructor) {
$context['has_constructor'] = true;
if (true !== $constructor->isPublic()) {
return $reflectionClass->newInstanceWithoutConstructor();
}
$constructorParameters = $constructor->getParameters();
$missingConstructorArguments = [];
$params = [];
$unsetKeys = [];
foreach ($constructorParameters as $constructorParameter) {
$paramName = $constructorParameter->name;
$attributeContext = $this->getAttributeDenormalizationContext($class, $paramName, $context);
$key = $this->nameConverter ? $this->nameConverter
->normalize($paramName, $class, $format, $context) : $paramName;
$allowed = false === $allowedAttributes || \in_array($paramName, $allowedAttributes, true);
$ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context);
if ($constructorParameter->isVariadic()) {
if ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
if (!\is_array($data[$key])) {
throw new RuntimeException(\sprintf('Cannot create an instance of "%s" from serialized data because the variadic parameter "%s" can only accept an array.', $class, $constructorParameter->name));
}
$variadicParameters = [];
foreach ($data[$key] as $parameterKey => $parameterData) {
try {
$variadicParameters[$parameterKey] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format);
} catch (NotNormalizableValueException $exception) {
if (!isset($context['not_normalizable_value_exceptions'])) {
throw $exception;
}
$context['not_normalizable_value_exceptions'][] = $exception;
$params[$paramName] = $parameterData;
}
}
$params = array_merge(array_values($params), $variadicParameters);
$unsetKeys[] = $key;
}
}
elseif ($allowed && !$ignored && (isset($data[$key]) || \array_key_exists($key, $data))) {
$parameterData = $data[$key];
if (null === $parameterData && $constructorParameter->allowsNull()) {
$params[$paramName] = null;
$unsetKeys[] = $key;
continue;
}
try {
$params[$paramName] = $this->denormalizeParameter($reflectionClass, $constructorParameter, $paramName, $parameterData, $attributeContext, $format);
} catch (NotNormalizableValueException $exception) {
if (!isset($context['not_normalizable_value_exceptions'])) {
throw $exception;
}
$context['not_normalizable_value_exceptions'][] = $exception;
$params[$paramName] = $parameterData;
}
$unsetKeys[] = $key;
}
elseif (\array_key_exists($key, $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
$params[$paramName] = $context[static::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
}
elseif (\array_key_exists($key, $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class] ?? [])) {
$params[$paramName] = $this->defaultContext[self::DEFAULT_CONSTRUCTOR_ARGUMENTS][$class][$key];
}
elseif ($constructorParameter->isDefaultValueAvailable()) {
$params[$paramName] = $constructorParameter->getDefaultValue();
}
elseif (!($context[self::REQUIRE_ALL_PROPERTIES] ?? $this->defaultContext[self::REQUIRE_ALL_PROPERTIES] ?? false) && $constructorParameter->hasType() && $constructorParameter->getType()
->allowsNull()) {
$params[$paramName] = null;
}
else {
if (!isset($context['not_normalizable_value_exceptions'])) {
$missingConstructorArguments[] = $constructorParameter->name;
continue;
}
$constructorParameterType = 'unknown';
$reflectionType = $constructorParameter->getType();
if ($reflectionType instanceof \ReflectionNamedType) {
$constructorParameterType = $reflectionType->getName();
}
$exception = NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class misses the "%s" property.', $constructorParameter->name), null, [
$constructorParameterType,
], $attributeContext['deserialization_path'] ?? null, true);
$context['not_normalizable_value_exceptions'][] = $exception;
}
}
if ($missingConstructorArguments) {
throw new MissingConstructorArgumentsException(\sprintf('Cannot create an instance of "%s" from serialized data because its constructor requires the following parameters to be present : "$%s".', $class, implode('", "$', $missingConstructorArguments)), 0, null, $missingConstructorArguments, $class);
}
if (!$constructor->isConstructor()) {
$instance = $constructor->invokeArgs(null, $params);
// do not set a parameter that has been set in the constructor
foreach ($unsetKeys as $key) {
unset($data[$key]);
}
return $instance;
}
try {
$instance = $reflectionClass->newInstanceArgs($params);
// do not set a parameter that has been set in the constructor
foreach ($unsetKeys as $key) {
unset($data[$key]);
}
return $instance;
} catch (\TypeError $e) {
if (!isset($context['not_normalizable_value_exceptions'])) {
throw $e;
}
return $reflectionClass->newInstanceWithoutConstructor();
}
}
unset($context['has_constructor']);
if (!$reflectionClass->isInstantiable()) {
throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Failed to create object because the class "%s" is not instantiable.', $class), $data, [
'unknown',
], $context['deserialization_path'] ?? null);
}
return new $class();
}