我正在研究collection form这称为目标,用户可以添加任意数量的目标,这部分工作正常,我能够显示/添加/编辑/删除目标就好了
我遇到的问题是如何验证数据 . 在表单上有一个 goal target
(整数)字段和 saved to date
(整数)字段 .
规则是 saved to date
的值不能超过 goal target
,为此我创建了custom validation,并且在提交表单时选择该类 .
SavedToDate.php
namespace MyBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
class SavedToDate extends Constraint
{
public $message = '"%string%" Saved to date cannot be greater than target date.';
}
SavedToDateValidator.php
namespace MyBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class SavedToDateValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
$values = $this->context->getRoot()->getdata()->getGoals()->getValues();
foreach($values as $item ){
$target = $item->getTarget();
$savedToDate = $item->getReached();
if ($savedToDate > $target) {
$this->context->buildViolation($constraint->message)
->setParameter('%string%', $value)
->addViolation();
}
}
}
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}
从阅读symfony文档看来,我似乎需要在 validation.yml
中添加约束Valid .
goals:
- Valid:
问题1
假设我输入的 saved to date
大于第一个目标 goal target
,而不是仅针对该目标获得错误,我得到两个目标的错误 .
NOTE 第二个错误不应该存在,因为8000小于20000
问题2
假设我反对这两个目标 saved to date
大于 goal target
我然后看到每个字段有2个错误 .
This is my view template
{% for goals in form.goals %}
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
{% if(form_errors(goals.target)) %}
<div class="alert alert-danger" role="alert">{{ form_errors(goals.target) }}</div>
{% endif %}
{% if(form_errors(goals.reached)) %}
<div class="alert alert-danger" role="alert">{{ form_errors(goals.reached) }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col-xs-2" style="padding-top: 5%">
<label class="" for="exampleInputEmail2">Goal target</label>
<div class="form-group input-group">
{{ form_widget(goals.target, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
<div class="col-xs-2" style="padding-top: 5%">
<label class="" for="exampleInputEmail2">Saved to date</label>
<div class="form-group input-group">
{{ form_widget(goals.reached, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
<div class="col-xs-2" style="padding-top: 5%">
<label class="" for="exampleInputEmail2">Goal deadline</label>
<div class="form-group input-group">
{{ form_widget(goals.deadline, {'attr': {'class': 'form-control dp'}}) }}
</div>
</div>
<div class="col-xs-2" style="padding-top: 5%">
<label class="" for="exampleInputEmail2">Savings</label>
<div class="form-group input-group">
{{ form_widget(goals.allocated, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
</div>
{% endfor %}
This is my Action
public function prioritiseGoalsAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
//get user id of currently logged in user
$userId = $this->getUser()->getId();
//get survey object of currently logged in user
$userGoalsInfo = $em->getRepository('MyBundle:survey')->findOneByuserID($userId);
//create the form
$form = $this->createForm(new GoalsType(), $userGoalsInfo);
$form->handleRequest($request);
if ($request->isMethod('POST')) {
if ($form->isValid()) {
$em->persist($userGoalsInfo);
$em->flush();
$this->get('session')->getFlashBag()->add(
'notice',
'Your Goals information has been saved'
);
return $this->render('MyBundle:Default/dashboard:prioritise-my-goals.html.twig', array(
'form' => $form->createView(),
));
}
}
return $this->render('MyBundle:Default/dashboard:prioritise-my-goals.html.twig', array(
'form' => $form->createView(),
));
}
在这一点上,我很无能为力,因为我花了几个小时试图解决这个问题,我真的很感激这方面的任何帮助 .
2 回答
最后我能够解决问题 .
Constraint
类中添加以下代码 . 在我的情况下,这是SavedToDate
,我在SavedToDateValidator
中添加它是错误的 .SavedToDateValidator
的validate()
函数,感谢@Richard提示 .以上函数的一个重要部分是
->atPath('reached')
这个atPath()
将错误粘贴到违规的字段,我之前没有这个,这导致显示针对所有字段的错误消息而不是唯一针对错误的字段实际上属于 .atpath('fieldname')
中的参数是您要将错误链接到的属性名称 . 但为了使其工作,您还需要关闭error_bubbling,以便错误不会传递给父窗体 .这个解决方案对我有用,我必须承认它真的很有趣,让我很兴奋 .
这是一个类级别约束,它将触发您从表单中保留的目标类的每个实例 .
因为您在验证器中遍历所有对象(为什么?),所以您将检查所有目标实体,这是不理想的(对于2x实体,您将检查每个实体2x,3x实体,你将检查每个实体3x等) .
请注意,这里的$ value是您的类对象,因此无需查看验证器中的其他实体 .
您应该编写类似的验证器(我没有检查语法):
阅读class constraint validators的文档