Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit af9fa66

Browse filesBrowse files
bug #53530 [Serializer] Rewrite AbstractObjectNormalizer::createChildContext() to use the provided cache_key from original context when creating child contexts (amne)
This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [Serializer] Rewrite `AbstractObjectNormalizer::createChildContext()` to use the provided `cache_key` from original context when creating child contexts | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | N/A | License | MIT If the normalization starts with an initial 'cache_key' it is currently discarded when creating child contexts. This change fixes that. The main reason behind it is that if the client code sends a unique identifier (ApiPlatform injects the IRI) and we have a use case that iterates a big resultset we end up with a big private cache that quickly runs out of allowed memory. The solution should be to send a 'cache_key' which skips the entire cache key calculation that hashes the context. Commits ------- db412fe [Serializer] Rewrite `AbstractObjectNormalizer::createChildContext()` to use the provided `cache_key` from original context when creating child contexts
2 parents 6b1be02 + db412fe commit af9fa66
Copy full SHA for af9fa66

File tree

2 files changed

+130
-1
lines changed
Filter options

2 files changed

+130
-1
lines changed

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,11 @@ private function isMaxDepthReached(array $attributesMetadata, string $class, str
781781
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
782782
{
783783
$context = parent::createChildContext($parentContext, $attribute, $format);
784-
$context['cache_key'] = $this->getCacheKey($format, $context);
784+
if ($context['cache_key'] ?? false) {
785+
$context['cache_key'] .= '-'.$attribute;
786+
} else {
787+
$context['cache_key'] = $this->getCacheKey($format, $context);
788+
}
785789

786790
return $context;
787791
}

‎src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php
+125Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,131 @@ public function testDenormalizeUntypedStringObject()
548548
$this->assertEquals(new DummyWithStringObject(new DummyString()), $actual);
549549
$this->assertEquals('', $actual->value->value);
550550
}
551+
552+
public function testProvidingContextCacheKeyGeneratesSameChildContextCacheKey()
553+
{
554+
$foobar = new Dummy();
555+
$foobar->foo = new EmptyDummy();
556+
$foobar->bar = 'bar';
557+
$foobar->baz = 'baz';
558+
$data = [
559+
'foo' => [],
560+
'bar' => 'bar',
561+
'baz' => 'baz',
562+
];
563+
564+
$normalizer = new class() extends AbstractObjectNormalizerDummy {
565+
public $childContextCacheKey;
566+
567+
protected function extractAttributes(object $object, string $format = null, array $context = []): array
568+
{
569+
return array_keys((array) $object);
570+
}
571+
572+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
573+
{
574+
return $object->{$attribute};
575+
}
576+
577+
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
578+
{
579+
$childContext = parent::createChildContext($parentContext, $attribute, $format);
580+
$this->childContextCacheKey = $childContext['cache_key'];
581+
582+
return $childContext;
583+
}
584+
};
585+
586+
$serializer = new Serializer([$normalizer]);
587+
588+
$serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/1']);
589+
$firstChildContextCacheKey = $normalizer->childContextCacheKey;
590+
591+
$serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/2']);
592+
$secondChildContextCacheKey = $normalizer->childContextCacheKey;
593+
594+
$this->assertSame($firstChildContextCacheKey, $secondChildContextCacheKey);
595+
}
596+
597+
public function testChildContextKeepsOriginalContextCacheKey()
598+
{
599+
$foobar = new Dummy();
600+
$foobar->foo = new EmptyDummy();
601+
$foobar->bar = 'bar';
602+
$foobar->baz = 'baz';
603+
$data = [
604+
'foo' => [],
605+
'bar' => 'bar',
606+
'baz' => 'baz',
607+
];
608+
609+
$normalizer = new class() extends AbstractObjectNormalizerDummy {
610+
public $childContextCacheKey;
611+
612+
protected function extractAttributes(object $object, string $format = null, array $context = []): array
613+
{
614+
return array_keys((array) $object);
615+
}
616+
617+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
618+
{
619+
return $object->{$attribute};
620+
}
621+
622+
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
623+
{
624+
$childContext = parent::createChildContext($parentContext, $attribute, $format);
625+
$this->childContextCacheKey = $childContext['cache_key'];
626+
627+
return $childContext;
628+
}
629+
};
630+
631+
$serializer = new Serializer([$normalizer]);
632+
$serializer->normalize($foobar, null, ['cache_key' => 'hardcoded', 'iri' => '/dummy/1']);
633+
634+
$this->assertSame('hardcoded-foo', $normalizer->childContextCacheKey);
635+
}
636+
637+
public function testChildContextCacheKeyStaysFalseWhenOriginalCacheKeyIsFalse()
638+
{
639+
$foobar = new Dummy();
640+
$foobar->foo = new EmptyDummy();
641+
$foobar->bar = 'bar';
642+
$foobar->baz = 'baz';
643+
$data = [
644+
'foo' => [],
645+
'bar' => 'bar',
646+
'baz' => 'baz',
647+
];
648+
649+
$normalizer = new class() extends AbstractObjectNormalizerDummy {
650+
public $childContextCacheKey;
651+
652+
protected function extractAttributes(object $object, string $format = null, array $context = []): array
653+
{
654+
return array_keys((array) $object);
655+
}
656+
657+
protected function getAttributeValue(object $object, string $attribute, string $format = null, array $context = [])
658+
{
659+
return $object->{$attribute};
660+
}
661+
662+
protected function createChildContext(array $parentContext, string $attribute, ?string $format): array
663+
{
664+
$childContext = parent::createChildContext($parentContext, $attribute, $format);
665+
$this->childContextCacheKey = $childContext['cache_key'];
666+
667+
return $childContext;
668+
}
669+
};
670+
671+
$serializer = new Serializer([$normalizer]);
672+
$serializer->normalize($foobar, null, ['cache_key' => false]);
673+
674+
$this->assertFalse($normalizer->childContextCacheKey);
675+
}
551676
}
552677

553678
class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.