0

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
2
  • Is Status table already filled with the data, and when inserting new User, you are just choosing a corresponding status for that user? Commented Nov 25, 2016 at 9:29
  • @MatkoĐipalo Yes, the user table only stores the id from Status in a statusid column. I just added a table overview in my question. Commented Nov 25, 2016 at 9:35

1 Answer 1

2

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 :)

Sign up to request clarification or add additional context in comments.

2 Comments

You know, I use form events all the time and not once did I think I could use them for this. You sir, are a gentleman and a scholar. Thank you! However, I didn't have to convert the JSON data to an array. It seems the form submit() takes care of that as well.
I am glad I could help you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.