Skip to content

Instantly share code, notes, and snippets.

@webmozart
Created June 22, 2015 18:55
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save webmozart/36b1cd8a68a5f7844268 to your computer and use it in GitHub Desktop.
Save webmozart/36b1cd8a68a5f7844268 to your computer and use it in GitHub Desktop.
class MoneyType extends AbstractType implements DataMapperInterface
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('amount', 'integer')
->add('currency', 'string')
->setDataMapper($this)
;
}
public function mapDataToForms($data, $forms)
{
foreach ($forms as $form) {
switch ($form->getName()) {
case 'amount':
$form->setData($data->getAmount());
break;
case 'currency':
$form->setData($data->getCurrency());
break;
}
}
}
public function mapFormsToData($forms, &$data)
{
$forms = iterator_to_array($forms);
$data = new Money($forms['amount']->getData(), $forms['currency']->getData());
}
}
@mmoreram
Copy link

Thanks @webmozart. That's exactly what I was looking for.

@dadamssg
Copy link

why not just use empty_data?

class MoneyType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $builder
            ->add('amount', 'integer')
            ->add('currency', 'string');
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'empty_data' => function (FormInterface $form) {
                return new Money($form->get('amount')->getData(), $form->get('currency')->getData());
            }
        ]);
    }
}

@stof
Copy link

stof commented Jun 22, 2015

@dadamssg empty_data does not work when the form is bound to an instance to update it

@dadamssg
Copy link

@stof ah gotcha. Thanks

@gnat42
Copy link

gnat42 commented Jun 23, 2015

So this is nice and an interesting way to solve this problem. I'm just wondering isn't this the purpose of data transformers?

@jaspernbrouwer
Copy link

How does this behave when user input breaks the invariants of Money? Will validation by the form take care of this? Or will Money throw an exception because it is instantiated before form validation is performed?

@webmozart
Copy link
Author

@jaspernbrouwer You could catch the exceptions thrown by Money and wrap them into a TransformationFailedException.

@gnat42 Exchanging information between the data of a form and its children is the responsibility of the data mapper. You could use a data transformer too and transform Money to/from an array, but then you'd need to set the data mapper to something like a NullDataMapper because then you do the mapping yourself.

@cordoval
Copy link

cordoval commented Jul 6, 2015

would be nice to gets its usage too like:

$form = $this->createForm(new MoneyType(), $user->getInvestment());
if ($form->handleRequest($request)->isValid()) {
    $this->bus->dispatch(new UpdateInvestment($user->getId(), $form->getData()))

and also say that should the type have less fields than the VO you can also copy those over to the VO from the $data coming into the call to mapFormsToData($forms, &$data)

😸

@webmozart
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment