![](/img/trans.png)
[英]How can I put the keys of an array in a ChoiceType element for Symfony
[英]How can I validate array keys using Symfony Validation?
如何使用Symfony验证来验证数组键?
说我有以下内容,并且emails
数组的每个键都是一个ID。 如何使用回调或其他约束(例如正则表达式约束而不是回调)来验证它们?
$input = [
'emails' => [
7 => 'david@panmedia.co.nz',
12 => 'some@email.add',
],
'user' => 'bob',
'amount' => 7,
];
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Constraints;
$validator = Validation::createValidator();
$constraint = new Constraints\Collection(array(
'emails' => new Constraints\All(array(
new Constraints\Email(),
)),
'user' => new Constraints\Regex('/[a-z]/i'),
'amount' => new Constraints\Range(['min' => 5, 'max' => 10]),
));
$violations = $validator->validateValue($input, $constraint);
echo $violations;
(使用最新的dev-master symfony)
我将创建一个自定义验证约束,该约束将约束应用于数组中的每个键值对(或仅在需要时才键)。 与“ All
约束类似,但验证是对键值对执行的,而不仅限于值。
namespace GLS\DemoBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
class AssocAll extends Constraint
{
public $constraints = array();
public function __construct($options = null)
{
parent::__construct($options);
if (! is_array($this->constraints)) {
$this->constraints = array($this->constraints);
}
foreach ($this->constraints as $constraint) {
if (!$constraint instanceof Constraint) {
throw new ConstraintDefinitionException('The value ' . $constraint . ' is not an instance of Constraint in constraint ' . __CLASS__);
}
}
}
public function getDefaultOption()
{
return 'constraints';
}
public function getRequiredOptions()
{
return array('constraints');
}
}
约束验证器,它将带有键值对的数组传递给每个约束:
namespace GLS\DemooBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
class AssocAllValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
if (null === $value) {
return;
}
if (!is_array($value) && !$value instanceof \Traversable) {
throw new UnexpectedTypeException($value, 'array or Traversable');
}
$walker = $this->context->getGraphWalker();
$group = $this->context->getGroup();
$propertyPath = $this->context->getPropertyPath();
foreach ($value as $key => $element) {
foreach ($constraint->constraints as $constr) {
$walker->walkConstraint($constr, array($key, $element), $group, $propertyPath.'['.$key.']');
}
}
}
}
我猜想,只有Callback
约束才有意义,可以将其应用于验证逻辑的每个键值对。
use GLS\DemoBundle\Validator\Constraints\AssocAll;
$validator = Validation::createValidator();
$constraint = new Constraints\Collection(array(
'emails' => new AssocAll(array(
new Constraints\Callback(array(
'methods' => array(function($item, ExecutionContext $context) {
$key = $item[0];
$value = $item[1];
//your validation logic goes here
//...
}
))),
)),
'user' => new Constraints\Regex('/^[a-z]+$/i'),
'amount' => new Constraints\Range(['min' => 5, 'max' => 10]),
));
$violations = $validator->validateValue($input, $constraint);
var_dump($violations);
有一个回调约束。 参见http://symfony.com/doc/master/reference/constraints/Callback.html
更新:
我找不到更干净的方法来获取正在验证的当前值的键。 可能有更好的方法,我没有花太多时间在此上,但是它适合您的情况。
use Symfony\Component\Validator\Constraints;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
// ...
$input = array(
'emails' => array(
7 => 'david@panmedia.co.nz',
12 => 'some@email.add',
),
'user' => 'bob',
'amount' => 7,
);
// inside a sf2 controller: $validator = $this->get('validator.builder')->getValidator();
$validator = Validation::createValidator();
$constraint = new Constraints\Collection(array(
'emails' => new Constraints\All(array(
new Constraints\Email(),
new Constraints\Callback(array('methods' => array(function($value, ExecutionContextInterface $context){
$propertyPath = $context->getPropertyPath();
$valueKey = preg_replace('/[^0-9]/','',$propertyPath);
if($valueKey == 7){
$context->addViolationAt('email', sprintf('E-Mail %s Has Has Key 7',$value), array(), null);
}
})))
)),
'user' => new Constraints\Regex('/[a-z]/i'),
'amount' => new Constraints\Range(array('min' => 5, 'max' => 10)),
));
$violations = $validator->validate($input, $constraint);
echo $violations;
有点晚了,但是我的朋友,您去了:
use Symfony\Component\Validator\Constraints as Assert;
public function getConstraints()
{
return [
'employee' => [new Assert\NotBlank(), new Assert\Type("integer")],
'terms' => [new Assert\NotBlank(), new Assert\Type("array")],
'pivotData' => new Assert\All([
new Assert\Type("array"),
new Assert\Collection([
'amount' => new Assert\Optional(new Assert\Type('double'))
])
]),
];
}
这里需要注意几件事:
在上面提供的示例中,我们正在验证数据pivotData
键。 pivotData
应该是我们要验证的额外数据的数组。
每次我们要验证数组时,我们都new Assert\\All
开始,这意味着我们要验证pivotData
所有pivotData
然后,我们添加新的Assert\\Type("array")
来检查是否确实从前端传递了数组。
而且,最重要的是,我们创建了一个new Assert\\Collection
,在其中我们作为标准一个一定义新属性。 在上面的示例中,我添加了一个代表枢轴数据属性的amount
键。 您可以在此处自由列出所有属性,它们将得到验证:)
祝好运 :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.