David
David

Reputation: 2783

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?

Upvotes: 0

Views: 1094

Answers (3)

Vincent Decaux
Vincent Decaux

Reputation: 10714

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.

Upvotes: 0

MacSte
MacSte

Reputation: 1

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")

Upvotes: 0

David
David

Reputation: 2783

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

Upvotes: 0

Related Questions