Уникальное ограничение Symfony2 с несколькими полями и mongodb

Я начал работать с Symfony2 и MongoDB (Doctrine ODM), и у меня возникли трудности с тем, чтобы уникальное ограничение валидатора работало с несколькими полями (одно поле ссылается на другой документ MongoDB с DBRef). В моем файле validation.yml у меня есть:

Acme\SomeBundle\Document\ArticlePosition:
    constraints:
        - Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique:
            fields: [position, section]

Поле «позиция» является целым числом, а «раздел» — это поле referenceOne, которое указывает на объект в другом пакете.

Когда я отправляю форму для этого, я вижу следующие запросы в профилировщике:

db.article_position.find({ "position": 1, "section": "51ff78494fae886b1f7c0f1d" });
db.article_position.insert({ "000000005dc659f30000000082e5d25d": { "_id":ObjectId("5203d1804fae880e801fd12d"), "position": 1, "section": { "$ref": "section", "$id": ObjectId("51ff78494fae886b1f7c0f1d"), "$db": "my_db" } } });

Symfony/Doctrine выглядит так, как будто они пытаются поступать правильно. Первый метод find() ищет соответствующий документ с полем position и section, но в нем отсутствуют поля DBRef ($ref, $id, $db) и всегда возвращается пустой набор.

Запрос find() должен быть таким:

db.article_position.find({ "position": 1, "section": { "$ref": "section", "$id": ObjectId("51ff78494fae886b1f7c0f1d"), "$db": "my_db" }});

Мой файл доктрины YAML выглядит так:

Acme\SomeBundle\Document\ArticlePosition
    type: document
    collection: article_position
    referenceOne:
        section:
            targetDocument: Acme\SomeOtherBundle\Document\Section
    fields:
        id:
            type: id
            id: true
        position:
            type: int

Документ section находится в отдельном пакете от документа ArticlePosition.


person burr    schedule 08.08.2013    source источник


Ответы (1)


Это скорее обходной путь, чем решение.

Во-первых, в вашем контроллере вы должны вручную связать раздел со ArticlePosition, прежде чем вызывать $form->isValid().

$entity = new ArticlePosition();
$entity->setSection($section); 
...
$form->handleRequest($request);
if ($form->isValid()) {
    ...
}

Во-вторых, вы должны указать пользовательский метод репозитория для ограничения Unique.

# validation.yml
Acme\DefaultBundle\Document\ArticlePosition:
    constraints:
        - Doctrine\Bundle\MongoDBBundle\Validator\Constraints\Unique:
            fields: [section, position]
            repositoryMethod: findUniqueBy

и в вашем ArticlePositionRepository

public function findUniqueBy($criteria)
{
    $section = $criteria['section'];
    $position = $criteria['position'];

    return $this->findBy(array('section.id' => $section, 'position' => $position));
}

Ключевым моментом здесь является добавление .id для ссылочных полей в findBy, чтобы Mongodb правильно запрашивал результат.

person Mr. 14    schedule 02.03.2014