4

I'm having trouble implementing something in Zf2 and Doctrine2 using MongoDB that's fairly straightforward in Symfony2 and Doctrine2.

I have an Invoice Document where I want to make sure the combination of the Invoice::pattern and Invoice::number is unique. A number can appear multiple times, same as the pattern but the combination of the pattern and invoice number should be unique.

In Symfony2 I would use the bridge

use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

@UniqueEntity({"pattern", "number"})
class Invoice
{
...

But this doesn't work in Zf2 for obvious reasons.

My current annotation setup in Zend Framework 2 is

/**
 * Class Invoice
 * @package Common\Document\Billing
 *
 * @ODM\Document(
 *     collection="invoice"
 * )
 * @ODM\UniqueIndex(keys={"prefix"="asc", "number"="asc"})
 * @ODM\ChangeTrackingPolicy("DEFERRED_IMPLICIT")
 */
class Invoice
{
...

But this does actually allow an invoice being persisted with the same pattern and number.

edigu
  • 9,878
  • 5
  • 57
  • 80
Simon
  • 1,643
  • 7
  • 30
  • 61

1 Answers1

2

I'm afraid you're comparing apples with pears here.

Doctrine MongoDB ODM

The @ODM\UniqueIndex index is part of Doctrine MongoDB ODM. It's purpose is to create/update an index when running the console commands odm:schema:create / odm:schema:update. MongoDB uses those indexes to speed up lookups.

When creating a unique index, MongoDB will enforce that uniqueness. You can see this as a sort of validation on a database level.

Because this all is part of Doctrine MongoDB ODM and MongoDB itself, you can use it in whatever framework you want. Symfony 2 or Zend Framework 2 doesn't make a difference here.

User input validation

The @UniqueEntity annotation is part of Symfony 2's Validator Component. This component can be used on its own, but most developers use the Form Component, which in turn uses the Validator component for form validation. Its purpose is to validate user input.

In other words: This kind of validation is completely different from what MongoDB does. While the Validator component enforces rules when user input is received (thus before data is sent to a database), MongoDB enforces data integrity while it tries to store it (thus after data is sent to the database).

Equivalent in ZF2

I think you're searching for an equivalent of the @UniqueEntity annotation in Zend Framework 2. You'll need to look towards the ZF2 Form, or at least the ZF2 Validator.

You're probably using the ZF2 DoctrineModule, or at least the the ZF2 DoctrineMongoODMModule. Have a look at the validator documentation of ZF2 DoctrineModule to see how to use this.

Jasper N. Brouwer
  • 21,517
  • 4
  • 52
  • 76
  • The problem with @ODM\UniqueIndex in DoctrineMongoDB is that the insert fails silently and doesn't throw an exception. The $dm->flush(["safe" => true]); has been deprecated so currently I'm stuck handling a failed insert. – Simon Oct 24 '14 at 14:28
  • The constraint is a database level thing. I don't have any experience with Doctrine Mongo ODM, so I'll believe you when you say that the persistence failure doesn't bubble up to the ODM. __But__ the point I'm trying to make is that you're comparing apples (framework-level validation) with pears (db-level constraints). If you want something like SF2's `@UniqueEntity` behavior in ZF2 you're going to need a ZF2 Validator (like the one in DoctrineModule). – Jasper N. Brouwer Oct 24 '14 at 14:34