我有一个带有动态表单集合的表单。关键是我不想让用户删除特定条目(在应用程序的其他部分修改)。所以我添加了一个有效的特定验证约束:如果我删除了一个不是" deletable"的元素,那么表单无效。
问题在于,当用户提交的元素被删除时,该元素不再在表单中,并且在提交表单数据后被锁定。
以下是显示问题的示例:
class AppointmentController extends Controller
{
public function editAppointment(Request $request, Appointment $appointment)
{
// Here
// count($appointment->getSlot()) === 3
$form = $this->createForm('appointment', $appointment, [
'questionnaire' => $questionnaire
]);
$form->handleRequest($request);
if ($form->isValid()) {
// Persisting
}
// Here on failing validation, there is
// count($appointment->getSlot()) === 2
// Because we removed one slot from "dynamically" in the form, but the user can't do that,
// so we need to reset the slots but it's not possible because form data is locked after "submit".
return $this->render('App:Appointment:edit.html.twig', ['form' => $form->createView()]);
}
}
class AppointmentType extends AbstractTYpe
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('slots', 'collection', [
'type' => new SlotType(),
'allow_add' => true,
'prototype' => true,
'allow_delete' => true,
'error_bubbling' => false,
'by_reference' => false,
'constraints' => [
new WrongSlotRemoval($builder->getData()->getSlots())
]
])
;
}
}
class WrongSlotRemoval extends Constraint
{
public $message = 'Impossible to delete slog.';
/**
* @var null|\App\Entity\AppointmentSlot[]
*/
private $slots;
/**
* @param \App\Entity\AppointmentSlot[]|null $slots
*/
public function __construct($slots = null)
{
// Clone the collection because it can be modified by reference
// in order to add or delete items.
if ($slots !== null) {
$this->slots = clone $slots;
}
}
/**
* @return \App\Entity\AppointmentSlot[]
*/
public function getSlots()
{
return $this->slots;
}
/**
* @param \App\Entity\AppointmentSlot[] $slots
* @return self
*/
public function setSlots($slots)
{
$this->slots = $slots;
return $this;
}
}
class WrongSlotRemovalValidator extends ConstraintValidator
{
/**
* @param \App\Entity\AppointmentSlot[] $object
* @param WrongSlotRemoval $constraint
*/
public function validate($object, Constraint $constraint)
{
foreach($constraint->getSlots() as $slot) {
if (!$object->contains($slot) && !$slot->isDeletable()) {
$this->context
->buildViolation($constraint->message)
->addViolation()
;
return;
}
}
}
}
有关如何在提交后修改表单数据的想法吗?
答案 0 :(得分:0)
这是一个Symfony限制:https://github.com/symfony/symfony/issues/5480
存在一种解决方法:重新创建表单并将表单的每个节点的错误复制到新表单(包含良好数据)。
我的解决方案是在验证程序中抛出错误,因为用户无法删除项目(交叉被禁用),因此他攻击了系统。显示错误不是问题。