0

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?

David
  • 2,603
  • 4
  • 18
  • 28

3 Answers3

0

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 ...

David
  • 2,603
  • 4
  • 18
  • 28
0

I don't know about lower versions but for Symfony 4.4 it's sufficient to overwrite service parameter to doctrine_odm.mongodb.unique:

@UniqueEntity(fields={"baz"}, service="doctrine_odm.mongodb.unique")
MacSte
  • 1
0

In Symfony, you can use this Annotation (or Attribute) instead since 5.4:

use Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique As UniqueEntity;

It just extends the Unique entity and set the service to mongoDb, nothing more.

Vincent Decaux
  • 9,857
  • 6
  • 56
  • 84