У меня есть 2 сопоставленных объекта,
коробка
class Box{
//[...]
/**
* @ORM\ManyToMany(targetEntity="Candy", cascade={"remove"})
* @ORM\OrderBy({"power" = "DESC"})
* @ORM\JoinTable(name="box_candies",
* joinColumns={@ORM\JoinColumn(name="box_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="candy_id", referencedColumnName="id", unique=true)}
* )
*/
private $candies;
}
И конфеты
class Candy
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
//[...]
}
Как видите, это Один-ко-многим, однонаправленный с таблицей соединений ассоциация. Коробка может «хранить» конфеты, но Кенди ничего не знает о коробке (где находится).
Теперь у меня есть страница, где я могу сделать конфеты и есть форма и стандарт isValid()
и после этого:
$box->addCandy($candy);
$entity_manager->persist($candy);
$entity_manager->persist($box);
$entity_manager->flush();
Теперь, где моя проблема?
Я хотел бы, чтобы коробка могла хранить только уникальные конфеты название), это означает, что Box может хранить объекты Candy с именами «Чоко» и «Апельсин» но не могу «Майонез» и «Майонез»
При изготовлении конфет я не могу проверить с UniqueEntity
ограничение, потому что конфеты не знают о коробке. Я думал о Callback
валидатор для Box или создание собственной Constraint, но я думаю, что лучше спросить:
Как я должен это делать?
Ответ запоздал, но может кому-то помочь, так что это решение я реализовал:
В моем случае я могу создать Candy
только в одном месте через форму, так что, наконец, я решил создать дополнительную специальную проверку для этого случая в моем контроллере / службе.
Проще говоря, я сделал код, проверяющий имя по-своему, а когда он недействителен, просто создаю trow Error
чтобы предотвратить создание. Я хочу подчеркнуть, что это немного грязное решение, а также оно не масштабируется, потому что вы должны всегда помнить, чтобы добавлять его в правильном месте, если вы создаете Candy в других местах.
// special unique name validation
$candy_name = $form->get('name')->getData();
if($candy_name){
$found_candy = $box->getCandyByName($candy_name);
if($found_candy){
$error = new FormError( $this->get('translator')->trans("candy.name.exist", array(), "validators") );
$form->get('name')->addError($error);
}
}
В любом случае это сработало, но в зависимости от вашего случая, Перезвоните может быть лучшим решением или даже простым UniqueEntity
ограничение.
Других решений пока нет …