Symfony2+Doctrine - 验证一对多实体集合

14

我有一个表单用于创建新实体。该实体包含一组其他实体,这些实体也在该表单中输入。

我想使用集合中实体的验证选项来验证这些实体,但它不起作用。会检查“主”实体(人)的验证规则,但不会检查addressList集合中实体(地址)的验证规则。当我在字段中输入无效信息时,提交的表单仍然能够通过验证。

在此示例中,街道注释未在验证中使用。

class Person 
{
    ...

    /**
     * @ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
     */
    protected $addressList;

    ....
}

class Address
{
    ...
    /**
     * @ORM\ManyToOne(targetEntity="Person", inversedBy="addressList")
     * @ORM\JoinColumn(name="person_id", referencedColumnName="id", onDelete="CASCADE")
     */
    protected $owner;

    /**
     * @ORM\Column(type="string", length=75)
     * @Assert\MinLength(
     *     limit=3,
     *     message="Street must have atleast {{ limit }} characters."
     * )
     */
    protected $street;

    ...

}

我该如何使表单验证所提供的地址实体?


3
我通过将'cascade_validation' => true添加到PersonType的getDefaultOptions()数组中来解决了这个问题。 - Bramklg
4个回答

15

我曾经遇到过相同的问题,但是通过以下方式解决:

/**
 * @ORM\OneToMany(
 *  targetEntity="Entity",
 *  mappedBy="mappedEntity",
 *  cascade={"persist" , "remove"}
 * )
 * @Assert\Valid
 */

这将验证列表中的每个地址是否为有效的地址实体。但是,如果您想要更多的验证,请查看下面@sergey-polischook的答案。 - Jekis
@Assert\Valid 使其验证集合的ManyToOne一侧上的所有约束条件,这正是我所需要的。 - Armel Larcier

7
我使用这个:
use Symfony\Component\Validator\ExecutionContextInterface;

class Person 
{
...

/**
 * @ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
 */
protected $addressList;

....

/**
 * @Assert\Callback
 */
public function validate(ExecutionContextInterface $context)
{
    if (!$this->getAddressList()->count()) {
        $context->addViolationAt(
            'addressList',
            'You must add at least one address',
            array(),
            null
        );
    }
}
}

http://symfony.com/doc/current/reference/constraints/Callback.html


同时在 $addressList 上添加 @Assert\Valid,这将是完整的解决方案。 - Jekis

6
只需要像下面这样添加注释断言。
/** 
 * @Assert\Count(
 *      min = "1",
 *      minMessage = "You must specify at least one"
 * )
 * @Assert\Valid 
 * 
 */
protected $name_of_collection_property;

0

你也可以在 "All" 约束条件中使用 "Valid" 约束条件:

/**
 * @ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
 * @Assert\All({
 *     @Assert\Valid
 * })
 */

protected $addressList;

2
你确定吗?这会在2.1版本中给我一个错误信息:“约束Valid不能嵌套在Symfony\Component\Validator\Constraints\All约束内。你只能直接在字段或方法上声明Valid约束。” - nurikabe
不太确定了。我想当时我使用的是2.0版本,而且我也遇到了类似的问题。如果这个方法行不通的话,也许我应该删除我的回答。 - Julien
1
我曾经遇到过类似的问题,使用3.3版本和@Assert\Valid()时,没有@Assert\All包围它似乎可以正常工作。显然,这也消除了“... Valid不能嵌套在... All...”错误消息。 - Andy Preston

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接