【问题标题】:Validate UniqueEntity for One-To-Many, Unidirectional with Join Table [Symfony2]使用连接表验证 UniqueEntity 的一对多、单向 [Symfony2]
【发布时间】:2015-12-30 04:45:55
【问题描述】:

我有 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;
    //[...]
}

如您所见,这是一对多、单向和连接表关联。 Box可以“存储”糖果,但Candy对Box一无所知(在哪里)。

现在我有了可以制作糖果的页面,并且有表格和标准isValid(),然后:

$box->addCandy($candy);
$entity_manager->persist($candy);
$entity_manager->persist($box);
$entity_manager->flush();

现在,我的问题在哪里?

我想 Box 可以存储 only 唯一的糖果(按名称),这意味着 Box 可以存储名称为 “Choco”和“Orange”的 Candy 对象" 但不能“蛋黄酱”和“蛋黄酱”

制作糖果时,我无法使用UniqueEntity 约束进行验证,因为糖果不知道盒子的存在。我考虑过 Callback Box 的验证器或创建自己的约束,但我认为最好问一下:

我应该怎么做?

【问题讨论】:

  • 请参阅 this post - 您应该在 Candy 实体的 name 字段上添加 UniqueEntity。当您在 Box 实体上执行 @ManyToMany 注释时,Doctrine 会自动将其视为您的复合主键并完全按照您的意愿强制执行唯一性。
  • 不,在我的情况下 name 不是唯一值
  • 为什么不是唯一值?
  • 在我的情况下,Candy 存在于许多 Boxes 中,但糖果名称对于每个 Box 都是唯一的,但并非同时适用于所有盒子
  • 我不确定我是否理解 - 但 Candy 是它自己的实体,与 Boxes 的任何东西完全无关,对吗?所以你的糖果桌上永远不会有 2 个“巧克力”条目。然后,每个盒子将简单地链接到其中的任何糖果,并以您已经拥有的多对多关系。

标签: php symfony symfony-forms symfony-validator


【解决方案1】:

回答迟了,但它可能对某人有所帮助,所以这是我实施的解决方案:

就我而言,我只能通过表单在一个地方创建Candy,所以最后我决定在我的控制器/服务中为这种情况创建额外的特殊验证。

简单地说,我以自己的方式对名称进行了代码检查,当它无效时,只需发送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);
        }
    }

无论如何它都有效,但根据您的情况,Callback 可能是更好的解决方案,甚至是简单的UniqueEntity 约束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    相关资源
    最近更新 更多