Por Jean Hertel, 10/03/2017, na categoria Dicas
Se você leu o nosso artigo sobre como configurar o Symfony Serializer com annotation e cache você já deve saber o básico da configuração necessária. Assim como o Serializer, o Validator também pode ler annotations e guardar os metadados da classe em cache.
Para ler as annotations, tudo que você precisa fazer é reescrever a função validator.mapping.class_metadata_factory
.
Esta função deve retornar uma instancia do objeto Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface
.
Se você quiser fazer isso, pode usar o seguinte snippet de código:
<?php
use Silex\Provider\ValidatorServiceProvider;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use Doctrine\Common\Annotations\AnnotationReader;
$app->register(new ValidatorServiceProvider());
$app['validator.mapping.class_metadata_factory'] = function ($app) {
$loader = new AnnotationLoader(new AnnotationReader());
return new LazyLoadingMetadataFactory($loader);
};
Desta forma o seu validador vai ler automáticamente as annotations que estiverem em sua classe.
Por fim, assim como no caso do serializer, para guardar os dados em cache você pode passar o segundo argumento da classe LazyLoadingMetadataFactory
.
A diferença a ser notada aqui, é que na versão atual do Symfony/Validator (3.2) a classe espera receber um parâmetro do tipo Symfony\Component\Validator\Mapping\Cache\CacheInterface
.
Felizmente, se você estiver usando o cache do Doctrine, já existe uma classe wrapper que pode ser usada, seu nome é DoctrineCache
.
A seguir um exemplo completo e funcional de toda a implementação:
<?php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Silex\Application;
use Silex\Provider\ValidatorServiceProvider;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
use \Memcache as MemcachePHP;
use Doctrine\Common\Cache\MemcacheCache as MemcacheWrapper;
use Symfony\Component\Validator\Constraints as Assert;
class Foo
{
/**
* @var int
* @Assert\NotBlank(message="This field cannot be empty")
*/
private $someProperty;
public function getSomeProperty() {
return $this->someProperty;
}
public function setSomeProperty($someProperty) {
$this->someProperty = $someProperty;
return $this;
}
}
$loader = require __DIR__ . '/vendor/autoload.php';
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 Application();
$app->register(new ValidatorServiceProvider());
$app['validator.mapping.class_metadata_factory'] = function ($app) use ($cacheDriver) {
$loader = new AnnotationLoader(new AnnotationReader());
$cache = new DoctrineCache($cacheDriver);
return new LazyLoadingMetadataFactory($loader, $cache);
};
$app->get('/', function (Application $app) {
$obj = new Foo();
$validationIssues = $app['validator']->validate($obj);
$errors = (string)$validationIssues;
return new \Symfony\Component\HttpFoundation\Response("Issues found: " . $errors);
});
$app->run();
Observação: Caso você esteja com algum erro de classe não encontrada, estou usando as seguintes depêndencias no meu composer.json: