Есть DTO с данными
<?php
namespace App\DTO\PaymentSystem;
use App\DTO\DataTransferObject;
class PaymentCreateDTO implements DataTransferObject
{
public $stripeProductId;
public $stripePlanId;
public $stripeSourceName;
public $stripeCoupon;
public $stripeToken;
public $stripeSource;
public $renew;
public $saveSource;
public $freeTrial;
}
есть маппер
Вот урезанная версия класса формы
public function buildForm(
FormBuilderInterface $builder,
array $options
): void {
parent::buildForm($builder, $options);
$builder
->add('stripeProductId', EntityType::class, [
'class' => StripeProduct::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('o')
->andWhere('o.active = :active')
->setParameter('active', true);
},
'choice_label' => 'name',
'choice_attr' => function (StripeProduct $stripeProduct) {
return [
'data-product-bugs-count' =>
$stripeProduct->product()->bugsCount(),
'data-product-name' =>
$stripeProduct->name()
];
}
])
//->add('stripePlanId', ChoiceType::class)
->add('renew', CheckboxType::class, [
'required' => false
])
->add('saveSource', CheckboxType::class, [
'required' => false
])
->add('freeTrial', CheckboxType::class, [
'required' => false
])
->add('stripeToken', HiddenType::class)
->add('stripeSource', HiddenType::class)
->add('stripeCoupon', TextType::class)
->add('stripeSourceName', TextType::class)
->setDataMapper(new PaymentCreateMapper2());
$builder
->get('stripeProductId')
->addModelTransformer(new CallbackTransformer(
function ($value) {
return $value;
},
function (StripeProduct $value) {
return $value->getId();
}
));
$formModifier = function (FormInterface $form, string $stripeProductId = null) {
$form->add('stripePlanId', EntityType::class, [
'class' => StripePlan::class,
'query_builder' => function (EntityRepository $er) use ($stripeProductId) {
return $er
->createQueryBuilder('o')
->andWhere('o.active = :active')
->andWhere('o.stripeProduct = :stripeProduct')
->setParameter('active', true)
->setParameter('stripeProduct', $stripeProductId);
},
'choice_label' => 'name',
'choice_attr' => function (StripePlan $stripePlan) {
return [
'data-plan-name' =>
$stripePlan->name(),
'data-plan-price' =>
$stripePlan->price(),
'data-plan-free_trial' =>
$stripePlan->trialPeriodDays()
];
}
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
$form = $event->getForm();
/** @var PaymentCreateDTO $data */
$data = $event->getData();
$formModifier($form, $data->stripeProductId);
}
);
$builder->get('stripeProductId')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
//dd(2);
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
/** @var PaymentCreateDTO $data */
// $data = $event->getData();
// dd($data);
$stripeProductId = $event->getData();
//dd($stripeProductId);
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $stripeProductId);
}
);
}
parent::buildForm($builder, $options); - это вызов из базового класса, там просто валидация, чтобы не могли в билдер подсунуть не тот объект
public function buildForm(
FormBuilderInterface $builder,
array $options
): void {
$this->validate($options);
}
private function validate(array $options): void
{
if (!isset($options['data'])) {
throw new InvalidArgumentException(null, 'Missing data class.');
}
if (!$options['data'] instanceof $this->expectedClass) {
throw new UnexpectedTypeException(
$options['data'],
$this->expectedClass
);
}
}
В $data всегда пустой дто при отправке через аякс.
Как исправить ситуацию?
P.S. Но если даже забить на данный слушатель. у меня есть второй
$builder->get('stripeProductId')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$stripeProductId = $event->getData();
$formModifier($event->getForm()->getParent(), $stripeProductId);
}
);
В который ид приходит, НО на выходе я получаю Notice: Undefined index: stripeProductId при заполнении формы из дто
$forms['stripeProductId']->setData($data->stripeProductId);
Mapper
public function mapDataToForms($viewData, $forms)
{
/** @var FormInterface[] $forms */
$forms = iterator_to_array($forms);
// initialize form field values
$forms['stripeProductId']->setData($viewData->stripeProductId);
$forms['stripePlanId']->setData($viewData->stripePlanId);
$forms['stripeToken']->setData($viewData->stripeToken);
$forms['stripeSource']->setData($viewData->stripeSource);
$forms['stripeCoupon']->setData($viewData->stripeCoupon);
$forms['stripeSourceName']->setData($viewData->stripeSourceName);
if (isset($forms['freeTrial'])) {
$forms['freeTrial']->setData($viewData->freeTrial);
}
}
public function mapFormsToData($forms, &$viewData)
{
/** @var FormInterface[] $forms */
$forms = iterator_to_array($forms);
// as data is passed by reference, overriding it will change it in
// the form object as well
// beware of type inconsistency, see caution below
$data = new PaymentCreateDTO(
$forms['stripeProductId']->getData(),
$forms['stripePlanId']->getData(),
$forms['stripeToken']->getData(),
$forms['stripeSource']->getData(),
$forms['stripeCoupon']->getData(),
$forms['stripeSourceName']->getData()
);
}