Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process nested json with FOSRestBundle and symfony forms

By nested json I mean something that keeps address data in its own "address" array:

{
  "user": {
    "id": 999,
    "username": "xxxx",
    "email": "[email protected]",
    "address": {
      "street": "13th avenue",
      "place": 12
    }
  }
}

instead of flat one

{
  "user": {
    "id": 999,
    "username": "xxxx",
    "email": "[email protected]",
    "street": "13th avenue",
    "place": 12
  }
}

Flat one is processed fine there using User entity and it's properties: "id", "username" and "email". It is nicely validated using symfony form feature:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('username');
    $builder->add('email', 'email');
    $builder->add('password', 'password');
    $builder->add('street');
    $builder->add('place');
}

I want to have both "street" and "place" as properties in User entity, to store it all in one user table in the database, using doctrine. But the json I get comes from third party, so I can not modify it.

Is there any way of constructing the form so it can validate the json with "address" field correctly, still being able to keep all the user data in one table?

like image 925
BartBiczBoży Avatar asked Oct 28 '25 02:10

BartBiczBoży


1 Answers

This is a pretty good question. One solution that comes to mind is making an unmapped form and binding data manually using a form event, for example:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // Make a "nested" address form to resemble JSON structure
    $addressBuilder = $builder->create('address', 'form')
        ->add('place')
        ->add('street');

    $builder->add('username');
    $builder->add('email', 'email');
    $builder->add('password', 'password');
    // add that subform to main form, and make it unmapped
    // this will tell symfony not to bind any data to user object
    $builder->add($addressBuilder, null, ['mapped' => false]);

    // Once form is submitted, get data from address form
    // and set it on user object manually
    $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) {
        $user = $event->getData();
        $addressData = $event->getForm()->get('address')->getData();

        $user->setStreet($addressData['street']);
        $user->setPlace($addressData['place']);
    })
}
like image 157
Igor Pantović Avatar answered Oct 30 '25 17:10

Igor Pantović



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!