diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php index 6f348095e8d6..b39310b76799 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php @@ -24,6 +24,13 @@ class PropertyInfoCacheExtractor implements PropertyInfoExtractorInterface { private $propertyInfoExtractor; private $cacheItemPool; + + /** + * A cache of property information, first keyed by the method called and + * then by the serialized method arguments. + * + * @var array + */ private $arrayCache = []; public function __construct(PropertyInfoExtractorInterface $propertyInfoExtractor, CacheItemPoolInterface $cacheItemPool) @@ -98,22 +105,34 @@ private function extract($method, array $arguments) } // Calling rawurlencode escapes special characters not allowed in PSR-6's keys - $key = rawurlencode($method.'.'.$serializedArguments); - - if (\array_key_exists($key, $this->arrayCache)) { - return $this->arrayCache[$key]; + $encodedMethod = \rawurlencode($method); + if (\array_key_exists($encodedMethod, $this->arrayCache) && \array_key_exists($serializedArguments, $this->arrayCache[$encodedMethod])) { + return $this->arrayCache[$encodedMethod][$serializedArguments]; } - $item = $this->cacheItemPool->getItem($key); + $item = $this->cacheItemPool->getItem($encodedMethod); + $data = $item->get(); if ($item->isHit()) { - return $this->arrayCache[$key] = $item->get(); + $this->arrayCache[$encodedMethod] = $data[$encodedMethod]; + // Only match if the specific arguments have been cached. + if (\array_key_exists($serializedArguments, $data[$encodedMethod])) { + return $this->arrayCache[$encodedMethod][$serializedArguments]; + } + } + + // It's possible that the method has been called, but with different + // arguments, in which case $data will already be initialized. + if (!$data) { + $data = []; } $value = \call_user_func_array([$this->propertyInfoExtractor, $method], $arguments); - $item->set($value); + $data[$encodedMethod][$serializedArguments] = $value; + $this->arrayCache[$encodedMethod][$serializedArguments] = $value; + $item->set($data); $this->cacheItemPool->save($item); - return $this->arrayCache[$key] = $value; + return $this->arrayCache[$encodedMethod][$serializedArguments]; } }