Ich mache etwas Programmierung in Silex mit den Symfony-Komponenten und ich denke, ich habe einen Fehler mit den symfony/serializer
und symfony/validator
Komponenten gefunden.Werden diese Daten von einer anderen Komponente überschrieben?
Zuerst lassen Sie mich erklären, was ich zu erreichen trage, dann gehen wir zum Code. Mein Ziel ist es, eine Klasse mit Informationen wie Serialisierungsdirektiven und Validierungsdirektiven zu kommentieren. Da das Lesen dieser Annotationen eine kleine CPU kosten kann, speichere ich sie gerne im Speicher. Zu diesem Zweck verwende ich Memcache-Wrapper im Doctrine/Common/Cache
-Paket.
Das Problem, dem ich gegenüberstehe, ist, dass sowohl die symfony/serializer
als auch die symfony/validator
Metadaten mit dem Klassennamen als Schlüssel in den Cache schreiben. Wenn sie später versuchen, die Metadaten abzurufen, lösen sie eine Ausnahme aus, weil der Cache ungültige Metadaten hat, entweder eine Instanz von Symfony\Component\Validator\Mapping\ClassMetadata
oder Symfony\Component\Serializer\Mapping\ClassMetadataInterface
.
folgt ein reproduzierbares Beispiel (sorry, wenn seine große, habe ich versucht, so klein wie möglich zu machen):
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();
Nach dem Ausführen dieses Beispiels Sie fatale Fehler bekommen. Kann mir jemand bestätigen, dass ich hier keinen schweren Fehler mache?
Momentan ist meine Problemumgehung dafür die DoctrineCache
Klasse neu schreiben, die Verwendung eines Namespace für die Cache-Schlüssel. Es funktioniert, aber ich denke, es ist hässlich.