Por Jean Hertel, 15/03/2017, modificado 24/03/2017, na categoria Dicas
Se você leu meus artigos anteriores sobre como configurar o Serializer e o Validator do symfony para utilizarem cache, certamente você já notou a grande diferença de performance que isso traz. Porem, você também deve ter notado que ao utilizar o validator e o serializer em uma mesma classe você recebe erro fatal. Algo como:
Fatal error: Uncaught Error: Call to undefined method Symfony\Component\Validator\Mapping\ClassMetadata::getAttributesMetadata() in /var/www/test/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php on line 72
/* Ou ainda */
Fatal error: Uncaught TypeError: Argument 1 passed to Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory::mergeConstraints() must be an instance of Symfony\Component\Validator\Mapping\ClassMetadata, instance of Symfony\Component\Serializer\Mapping\ClassMetadata given, called in /var/www/test/vendor/symfony/validator/Mapping/Factory/LazyLoadingMetadataFactory.php on line 104 and defined in C:\www\xpath\vendor\symfony\validator\Mapping\Factory\LazyLoadingMetadataFactory.php on line 129
Isso ocorre porque tanto o serializer como o validator escrevem no cache as instancias de metada utilizando o nome da classe como chave. Ao extrair novamente o resultado do cache, ocorre um erro fatal, pois o objeto não é do tipo esperado.
A maneira mais simples de resolver este problema é adicionando um namespace diferente para cada um dos caches.
A classe base dos caches do Doctrine é Doctrine\Common\Cache\CacheProvider
.
Esta classe possui um método chamado setNamespace
que lhe permite fazer essa diferença.
Para evitar a duplicação na conexão com o servidor de cache você deve primeiro conectar e depois criar as instancias do provider. O snippet de código a seguir trata corretamente esta situação:
<?php
use \Memcache as MemcachePHP;
use Doctrine\Common\Cache\MemcacheCache as MemcacheWrapper;
$memcache = new MemcachePHP();
if (! $memcache->connect('localhost', '11211')) {
throw new \Exception('Unable to connect to memcache server');
}
$cacheDriverSerializer = new MemcacheWrapper();
$cacheDriverSerializer->setMemcache($memcache);
$cacheDriverSerializer->setNamespace('SerializerNameSpace');
$cacheDriverValidator = new MemcacheWrapper();
$cacheDriverValidator->setMemcache($memcache);
$cacheDriverValidator->setNamespace('ValidatorNameSpace');
Agora você pode usar livremente o serializer e o validator sem erros :)