8

鉴于此输入:

[
    'key' => 'value',
]

如何验证以确保:

  1. key属性存在
  2. 它的值是一个数组(包含任意数量的元素)

我希望这个约束能起作用

    $constraint = new Collection([
        'key' => new Required([
            new Type('array'),
            new Collection([
                'value' => new Required([
                    new NotBlank(),
                ]),
            ]),
        ]),
    ]);

但它会引发异常:

Symfony\Component\Validator\Exception\UnexpectedTypeException: Expected argument  of type "array or Traversable and ArrayAccess", "string" given

我错过了什么?

PS:是symfony v2.7.1

PPS:澄清一下:我知道可以使用回调。如果我想从头开始手动重新实现验证——我一开始就不会使用 symfony。所以问题特别是关于结合现有约束而不是关于使用回调约束..

4

3 回答 3

4

两天前我遇到了完全相同的问题

最后的结论是Symfony2验证没有“快速失败”验证。也就是说,即使您的Type()约束失败,它也会继续执行其他约束,因此会因UnexpectedTypeException异常而失败。

但是,我能够找到一种方法来解决这个问题:

$constraint = new Collection([
    'key' => new Required([
        new Type(['type' => 'array']),
        new Collection([
            // Need to wrap fields into this
            // in order to provide "groups"
            'fields' => [ 
                'value' => new Required([
                    new NotBlank(),
                ]),
            ],
            'groups' => 'phase2' // <-- THIS IS CRITICAL
        ]),
    ]),
]);

// In your controller, service, etc...
$V = $this->get('validator');

// Checks everything by `Collection` marked with special group
$violations = $V->validate($data, $constraint);

if ( $violations->count()){
    // Do something
}

// Checks *only* "phase2" group constraints
$violations = $V->validate($data, $constraint, 'phase2');

if ( $violations->count()){
    // Do something
}

希望这会有所帮助。就个人而言,我觉得我们需要这样做很烦人。服务中的某种“快速失败”标志validator会很有帮助。

于 2015-07-02T14:46:53.113 回答
2

您是说Collection约束应该失败而不是抛出异常,因为'value'is astring而不是array.

最近记录了一个 Symfony 错误:https ://github.com/symfony/symfony/issues/14943

于 2015-06-24T22:12:16.490 回答
1

在您可以实现自定义验证逻辑的地方使用Callback约束(文档)。

另一种方法是创建自定义约束和验证器类。(文档

于 2015-06-24T06:04:55.663 回答