如何手动将冲突映射到Symfony表单?
订单类型如何手动将冲突映射到Symfony表单?,symfony,Symfony,订单类型 $builder ->add('items', FormTypes\CollectionType::class, [ 'entry_type' => OrderItemType::class, 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false, 'label' => 'acme
$builder
->add('items', FormTypes\CollectionType::class, [
'entry_type' => OrderItemType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'acme.form.order.items',
])
->add('channel', ChannelSelectType::class, [
'required' => true,
'label' => 'acme.form.order.channel',
])
OrderItemType
$builder
->add('service', ServiceSelectType::class, [
'label' => 'acme.form.order_item.service',
])
->add('product', ProductSelectType::class, [
'label' => 'acme.form.order_item.product',
])
->add('quantity', FormTypes\IntegerType::class, [
'label' => 'acme.form.order_item.quantity',
]);
如何将错误映射到OrderItemType产品字段?
当产品应用于特定渠道时,订单项有效。但是我们无法在OrderItemType中获取提交的通道,
因为子窗体类型在其父窗体类型之前提交。因此$event->getForm()->getParent()->getData()->getChannel()为空。我唯一的办法
是验证OrderType中的订单项,或创建添加到order类的验证器。问题是如何将错误映射到OrderItemType产品字段
$orderItems = $order->getItems();
$channel = $order->getChannel();
foreach($orderItems as $index => $orderItem) {
$product = $orderItem->getProduct();
if (!$this->isProductAvailableForChannel($channel, $product)) {
$message = sprintf('product %ss is not available for channel "%s"', $product->getName(), $channel->getName());
}
if (null !== $message) {
$this->context
->buildViolation($this->constraint->message)
->setParameter($message)
->atPath("items.children[$index].product") // this doesn't work, the error will be added to root form.
->addViolation()
;
}
}
您可以在预提交事件上获取频道(
Symfony\Component\Form\FormEvents::pre\u submit
)
在那里,您可以为订单项添加基于渠道的验证
$addItems = function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$options = [];
if (is_array($data) && array_key_exists('channel', $data)) {
$options['constraints'] = [
new OrderItemConstraint(['channel' => $data['channel']])
];
}
$form->add('items', FormTypes\CollectionType::class, [
'entry_type' => OrderItemType::class,
'entry_options' => $options,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'label' => 'acme.form.order.items',
]);
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, $addItems);
$builder->addEventListener(FormEvents::PRE_SUBMIT, $addItems);