alt*_*aus 14 forms validation symfony symfony-2.5
我在Symfony的表单验证处理方面遇到了一些问题.我想基于其数据验证绑定到实体的表单.有很多信息如何使用FormEvents 动态修改表单字段.我在这个主题上缺少的是如何控制/修改验证.
我简化的用例是:
验证实现为Validator与Constraint::CLASS_CONSTRAINT作为目标(因为它是采取一些更多的东西进去).
我试过了:
FormEvents并添加一个额外的字段,如"忽略日期警告".......但从未找到有效的解决方案.使用基于单个属性的验证器的更简单的黑客攻击也无法解决问题.:(
是否有Symfony方式来动态控制验证?
编辑:我的代码如下所示:
use Doctrine\ORM\Mapping as ORM;
use Acme\Bundle\Validator\Constraints as AcmeAssert;
/**
* Appointment
*
* @ORM\Entity
* @AcmeAssert\DateIsValid
*/
class Appointment
{
/**
* @ORM\Column(name="title", type="string", length=255)
*
* @var string
*/
protected $title;
/**
* @ORM\Column(name="date", type="date")
*
* @var \DateTime
*/
protected $date;
}
Run Code Online (Sandbox Code Playgroud)
验证器用作服务:
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* Validates the date of an appointment.
*/
class DateIsValidValidator extends ConstraintValidator
{
/**
* {@inheritdoc}
*/
public function validate($appointment, Constraint $constraint)
{
if (null === $date = $appointment->getDate()) {
return;
}
/* Do some magic to validate date */
if (!$valid) {
$this->context->addViolationAt('date', $constraint->message);
}
}
}
Run Code Online (Sandbox Code Playgroud)
相应的Constraint类设置为以实体类为目标.
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class DateIsValid extends Constraint
{
public $message = 'The date is not valid!';
/**
* {@inheritdoc}
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
/**
* {@inheritdoc}
*/
public function validatedBy()
{
return 'acme.validator.appointment.date';
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:尝试FormEvents...我也尝试了所有不同的事件.
$form = $formFactory->createBuilder()
->add('title', 'text')
->add('date', 'date')
->addEventListener(FormEvents::WHICHONE?, function(FormEvent $event) {
$form = $event->getForm();
// WHAT TO DO HERE?
$form->getErrors(); // Is always empty as all events run before validation?
// I need something like
if (!$dateIsValid) {
$form->setValidationGroup('ignoreWarning');
}
});
Run Code Online (Sandbox Code Playgroud)
编辑3:正确声明约束.那不是问题:
services:
validator.acme.date:
class: AcmeBundle\Validator\Constraints\DateValidator
arguments: ["@acme.other_service"]
tags:
- { name: validator.constraint_validator, alias: acme.validator.appointment.date }
Run Code Online (Sandbox Code Playgroud)
验证是在实体上完成的,所有表单所做的就是执行对象的验证。您可以根据提交的数据选择组
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function(FormInterface $form) {
$data = $form->getData();
if (Entity\Client::TYPE_PERSON == $data->getType()) {
return array('person');
} else {
return array('company');
}
},
));
}
Run Code Online (Sandbox Code Playgroud)
我在嵌入式表单和级联验证上使用这种方法时遇到了问题
编辑:使用闪存来确定是否必须进行验证。
// service definition
<service id="app.form.type.callendar" class="%app.form.type.callendar.class%">
<argument type="service" id="session" />
<tag name="form.type" alias="my_callendar" />
</service>
// some controller
public function somAvtion()
{
$form = $this->get('app.form.type.callendar');
...
}
// In the form
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => function(FormInterface $form) {
$session = $form->getSession();
if ($session->getFlashBag()->get('callendar_warning', false)) {
return array(false);
} else {
return array('Validate_callendar');
}
},
));
}
Run Code Online (Sandbox Code Playgroud)