Skip to content

Instantly share code, notes, and snippets.

@webmozart
Created June 22, 2015 18:55
Show Gist options
  • Select an option

  • Save webmozart/36b1cd8a68a5f7844268 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

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

@dadamssg
Copy link
Copy Markdown

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
Copy Markdown

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
Copy Markdown

@stof ah gotcha. Thanks

@gnat42
Copy link
Copy Markdown

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
Copy Markdown

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
Copy Markdown
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
Copy Markdown

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
Copy Markdown
Author

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