2017-02-06 7 views
12

मैं सिम्फनी घटकों के साथ सिलेक्स में कुछ प्रोग्रामिंग कर रहा हूं और मुझे लगता है कि मुझे symfony/serializer और symfony/validator घटकों के साथ एक बग मिला है।क्या यह डेटा किसी अन्य घटक द्वारा ओवरराइट किया जा रहा है?

सबसे पहले मुझे समझाने दें कि मैं क्या हासिल करने के लिए खोज रहा हूं, तो चलिए कोड पर जाएं। मेरा उद्देश्य एक वर्ग को सीरियलाइजेशन निर्देशों के साथ-साथ सत्यापन निर्देशों के साथ एनोटेट करना है। चूंकि इन एनोटेशन के पढ़ने के लिए एक लिटल सीपीयू खर्च हो सकता है, मैं उन्हें स्मृति में कैश करना पसंद करता हूं। इस उद्देश्य के लिए, मैं Doctrine/Common/Cache पैकेज में memcache wrapper का उपयोग कर रहा हूं।

मुझे जिस समस्या का सामना करना पड़ता है वह यह है कि symfony/serializer और symfony/validator क्लास नाम का उपयोग करके कैश में मेटाडेटा लिखें। जब वे मेटाडेटा को बाद में पुनर्प्राप्त करने का प्रयास करते हैं, तो वे अपवाद फेंकते हैं, क्योंकि कैश में अमान्य मेटाडेटा है, या तो Symfony\Component\Validator\Mapping\ClassMetadata या Symfony\Component\Serializer\Mapping\ClassMetadataInterface का उदाहरण है।

use Symfony\Component\Serializer\Annotation\Groups; 
use Symfony\Component\Validator\Constraints as Assert; 

class Foo 
{ 
    /** 
    * @var int 
    * @Assert\NotBlank(message="This field cannot be empty") 
    */ 
    private $someProperty; 

    /** 
    * @return int 
    * @Groups({"some_group"}) 
    */ 
    public function getSomeProperty() { 
     return $this->someProperty; 
    } 
} 


use Doctrine\Common\Annotations\AnnotationReader; 
use \Memcache as MemcachePHP; 
use Doctrine\Common\Cache\MemcacheCache as MemcacheWrapper; 

$loader = require_once __DIR__ . '/../vendor/autoload.php'; 

\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader([$loader, 'loadClass']); 

$memcache = new MemcachePHP(); 

if (! $memcache->connect('localhost', '11211')) { 
    throw new \Exception('Unable to connect to memcache server'); 
} 

$cacheDriver = new MemcacheWrapper(); 
$cacheDriver->setMemcache($memcache); 

$app = new \Silex\Application(); 

$app->register(new Silex\Provider\SerializerServiceProvider()); 

$app['serializer.normalizers'] = function() use ($app, $cacheDriver) { 
    $classMetadataFactory = new Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory(
     new Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader(new AnnotationReader()), $cacheDriver); 

    return [new Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer($classMetadataFactory) ]; 
}; 

$app->register(new Silex\Provider\ValidatorServiceProvider(), [ 
    'validator.mapping.class_metadata_factory' => 
     new \Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory(
      new \Symfony\Component\Validator\Mapping\Loader\AnnotationLoader(new AnnotationReader()), 
      new \Symfony\Component\Validator\Mapping\Cache\DoctrineCache($cacheDriver) 
     ) 
]); 

$app->get('/', function(\Silex\Application $app) { 
    $foo = new Foo(); 

    $app['validator']->validate($foo); 
    $json = $app['serializer']->serialize($foo, 'json'); 

    return new \Symfony\Component\HttpFoundation\JsonResponse($json, \Symfony\Component\HttpFoundation\Response::HTTP_OK, [], true); 
}); 

$app->error(function (\Exception $e, \Symfony\Component\HttpFoundation\Request $request, $code) { 
    return new \Symfony\Component\HttpFoundation\Response('We are sorry, but something went terribly wrong.' . $e->getMessage()); 
}); 

$app->run(); 

इस उदाहरण आप घातक त्रुटियों मिल चलाने के बाद:

के बाद एक reproductible उदाहरण (खेद है अपने बड़े, मैं संभव के रूप में छोटे करने की कोशिश की है)। क्या कोई यह पुष्टि कर सकता है कि मैं यहां कोई कठोर गलती नहीं कर रहा हूं?

वर्तमान में इसके लिए मेरा कार्यप्रणाली DoctrineCache कक्षा को कैश कुंजी के लिए नामस्थान का उपयोग करने के लिए फिर से लिखना है। यह काम कर रहा है, लेकिन मुझे लगता है कि यह बदसूरत है।

उत्तर

2

मुझे लगता है कि आपको क्या करना है दो अलग CacheDrivers है। https://github.com/doctrine/cache/blob/master/lib/Doctrine/Common/Cache/CacheProvider.php देखें कि नामस्थानों का उपयोग कैसे किया जाता है।

आप किए जा सकेंगे:

$validatorCacheDriver = new MemcacheWrapper(); 
$validatorCacheDriver->setMemcache($memcache); 
$validatorCacheDriver->setNamespace('symfony_validator'); 

$serializerCacheDriver = new MemcacheWrapper(); 
$serializerCacheDriver->setMemcache($memcache); 
$serializerCacheDriver->setNamespace('symfony_serializer'); 

// note that the two drivers are using the same memcache instance, 
// so only one connection will be used. 

$app['serializer.normalizers'] = function() use ($app, $serializerCacheDriver) { 
    $classMetadataFactory = new Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory(
     new Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader(new AnnotationReader()), $serializerCacheDriver); 

    return [new Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer($classMetadataFactory) ]; 
}; 

$app->register(new Silex\Provider\ValidatorServiceProvider(), [ 
    'validator.mapping.class_metadata_factory' => 
     new \Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory(
      new \Symfony\Component\Validator\Mapping\Loader\AnnotationLoader(new AnnotationReader()), 
      new \Symfony\Component\Validator\Mapping\Cache\DoctrineCache($validatorCacheDriver) 
     ) 
]); 

मैं कोड छंटनी की है केवल भागों है कि समाधान में कुछ भूमिका निभाते हैं दिखाने के लिए। आशा है कि ये आपकी मदद करेगा!

संबंधित मुद्दे

 संबंधित मुद्दे