Tek Tek - 9 days ago 6
reST (reStructuredText) Question

form validation nested json object

I have a Symfony 3.1 REST application that uses serialized JSON objects from the client that get deserialized back into entity objects in Symfony.

The problem I'm having is that

User
has a foreign key for a
Status
table. When I try to create a user I have to POST JSON with the following format:

{"firstname": "Jane", "lastname": "Doe", "status": "1"}


However, I would like to submit the JSON in the format below instead. I'd like to take take the
id
part of the
status
JSON in the example below to insert into the foreign key column. The client sending the request already has objects with this format and serializing them and submitting it like this would be extremely simple and easier to work with.

{"firstname": "Jane", "lastname": "Doe", "status": {"id": 3, "type": "Pending"}


I don't know where to start. I'm thinking about data transformers but I'm not completely sure how to make it accept the JSON format I want and also validate it at the same time.

NewUserType.php

class NewUserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname')
->add('lastname')
->add('status')
;
}


DefaultController.php

public function postNewUserAction(Request $Request)
{
$form = $this->createForm(NewUserType::class, new User());
$form->submit($Request->request->all());
...//validate and persist...
}


User.php

class User
{
/**
* @ORM\ManyToOne(targetEntity="Status")
* @ORM\JoinColumn(name="statusid", referencedColumnName="id")
*/
private $status;


Status.php

class Status
{
...
private $id
...
private $type;


User Table

mysql> select * from user;
+----+----------+-----------+----------+
| id | statusid | firstname | lastname |
+----+----------+-----------+-----------+
| 1 | 3 | Jane | Doe |


Status table

id type
3 Pending

Answer

One thing you could use is a form event listener (https://symfony.com/doc/current/form/events.html)

In your controller convert JSON request data into an array:

public function postNewUserAction(Request $Request)
{
    $data = json_decode($Request->getContent(), true);
    $form = $this->createForm(NewUserType::class, new User());
    $form->submit($data);
    if (!$form->isValid()) {...
}

FormType:

class NewUserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder
            ->add('firstname')
            ->add('lastname')
            ->add('name')
            ->add('status', EntityType::class, array(
                    'class' => 'YourBundle:Status',
                    'choice_label' => 'id',
                ))
        ;

        $builder->addEventListener(
                FormEvents::PRE_SUBMIT,
                array($this, 'onPreSubmitData')
            );
    }

    public function onPreSubmitData(FormEvent $event)
    {
        $eventData = $event->getData();
        $status = $eventData['status'];
        unset($eventData['status']);

        $eventData['status'] = $status['id'];
        $event->setData($eventData);
    }

In onPreSubmitData method, you can just adapt the data from the request for your needs :)

Comments