Как сопоставить нарушение с формой Symfony вручную?

Тип заказа

$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',
    ])

Тип элемента заказа

$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()
            ;
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
0
354
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете получить канал на предварительном мероприятии (Symfony\Component\Form\FormEvents::PRE_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);

Другие вопросы по теме