简体   繁体   中英

FOSRestBundle EntityType not working in JSON

I am using Symfony 3.4 and FOSRestBundle for my APIs.
All the services are working fine except this one where I am posting an entity with a form and an EntityType field.

Controller:

public function createAssistanceCallAction(Request $request)
{
    $assistanceCall = new AssistanceCall();
    $form = $this->createForm(AssistanceCallType::class, $assistanceCall);

    $form->handleRequest($request);
    dump($form->isSubmitted(), $form->isValid());die;
}

Entity property:

/**
 * @var MobileAppUser
 *
 * @ORM\ManyToOne(targetEntity="MobileAppUser")
 * @ORM\JoinColumn(name="mobile_app_user_id", referencedColumnName="id", nullable=false)
 * @Assert\NotBlank
 */
protected $mobileAppUser;

Form:

/**
 * {@inheritdoc}
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('mobile_app_user', EntityType::class, array(
            'class' => 'AppBundle:MobileAppUser',
        ))
        ->add('save', SubmitType::class)
    ;
}

It's working fine with a normal POST :

curl -X POST http://mysite.local/api/users/1/create-assistance-call -F 'assistance_call[mobile_app_user]=26'

dump($form->isSubmitted(), $form->isValid());die; // true and true

It's not working with JSON format:

curl -X POST \
  http://mysite.local/api/users/1/create-assistance-call \
  -d '{
    "assistance_call": {
        "mobile_app_user": {
            "id": 1
        }
    }
}'

dump($form->isSubmitted(), $form->isValid());die; // false and false

What am I doing wrong in the JSON example?

Just to add to the first answer, you also need to modify your JSON payload.

You have to put directly your mobile_app_user id :

{
    "assistance_call": {
        "mobile_app_user": 1
    }
}

Since you are sending your json object as a request body and not as normal POST fields - you should json_decode request content first and then use $form->submit(...) to load your form with the data. The old good handleRequest() won't do here. Take a look at the following example:

public function createAssistanceCallAction(Request $request)
{
    $assistanceCall = new AssistanceCall();
    $form = $this->createForm(AssistanceCallType::class, $assistanceCall);

    //Notice the "true" argument passed to the json_decode
    $data = json_decode($request->getContent(), true);
    $form->submit($data);

    dump($form->isSubmitted(), $form->isValid());die;
}

You can also use FOSRestBundle BodyListener to decode json for you. To do that - add the following configuration entry:

fos_rest:
    body_listener:
      decoders:
          json: fos_rest.decoder.jsontoform

This still doesn't make $form->handleRequest() a good choice since it will only allow one method per form, so if you configure your form to do POST - the PUT requests will always fail without any explicit error messages.

So then you would amend the code above like this:

public function createAssistanceCallAction(Request $request)
{

    $assistanceCall = new AssistanceCall();
    $form = $this->createForm(AssistanceCallType::class, $assistanceCall);
    $form->submit($request->request->all());

    dump($form->isSubmitted(), $form->isValid());die;
}

Pay attention to the Content-Type header you send as if it is set to 'multipart/form-data' while having json payload in its body - decoder will fail.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM