symfonysilexdoctrine-mongodb

How to apply a unique validator constraint using Silex and Doctrine MongoDB ODM?


I'm using Silex and would like to apply uniqueness validator constraints on MongoDB documents.

The UniqueEntity validator constraint to be found in symfony/doctrine-bridge wasn't designed to work with doctrine/mongodb-odm but solely with the ORM since the service defined in Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity is doctrine.orm.validator.unique.

With Symfony however, there is a Unique constraint validator in the doctrine/mongodb-odm-bundle that can be used for this purpose.

Do I have to port the code of the bundle? Any workaround?


Solution

  • I found a solution using Saxulum Doctrine MongoDb providers:

    1 - Create the unique document constraint

    # file: /src/MySilexApplication/Constraint/UniqueDocument.php
    
    namespace MySilexApplication\Constraint;
    
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    
    /**
     * Constraint for the unique document validator
     *
     * @Annotation
     */
    class UniqueDocument extends UniqueEntity
    {
        public $service = 'doctrine_odm.mongodb.unique';
    }
    

    2 - Register the constraint in the Doctrine annotation registry

    # file: /app/bootstrap.php
    
    \Doctrine\Common\Annotations\AnnotationRegistry::registerFile(
        '/src/MySilexApplication/Constraint/UniqueDocument.php'
    );
    

    3 - Use and register Saxulum providers (see documentation on Github for params declaration)

    # file: /app/bootstrap.php
    
    use Saxulum\DoctrineMongoDb\Silex\Provider\DoctrineMongoDbProvider;
    use Saxulum\DoctrineMongoDbOdm\Silex\Provider\DoctrineMongoDbOdmProvider;
    use Saxulum\DoctrineMongodbOdmManagerRegistry\Silex\Provider\DoctrineMongodbOdmManagerRegistryProvider;
    
    $app->register(new DoctrineMongoDbProvider(), $params['mongodb']));
    $app->register(new DoctrineMongoDbOdmProvider(), $params['mongodb_odm']);
    $app->register(new DoctrineMongodbOdmManagerRegistryProvider());
    

    4 - Reference the constraint validator into the Silex validator service provider and declare it as a Silex service

    # file: /app/bootstrap.php
    
    use Silex\Provider\ValidatorServiceProvider;
    
    $app->register(new ValidatorServiceProvider(), array(
        'validator.validator_service_ids' => array(
            'doctrine_odm.mongodb.unique' => 'doctrine_odm.mongodb.unique',
        )
    ));
    
    $app['doctrine_odm.mongodb.unique'] = $app->share(function (Application $app) {
        return new Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator($app['doctrine']);
    });
    

    5 - At last, use it into your document class

    # file: /src/MySilexApplication/Document/Bar.php
    
    namespace MySilexApplication\Document;
    
    use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
    use MySilexApplication\Constraint\UniqueDocument as UniqueDocument;
    
    /**
     * @MongoDB\Document(collection="Foo")
     *
     * @UniqueDocument(fields={"baz"})
     */
    class Bar
    {
        /**
         * @var string
         *
         * @MongoDB\String
         */
        protected $baz;
    
        ...
    }
    

    If someone knows a better way ...