FOSRestBundle EntityType 在 JSON 中不工作

FOSRestBundle EntityType not working in JSON

我正在为我的 API 使用 Symfony 3.4 和 FOSRestBundle。
所有服务都运行良好,除了我在其中发布带有表单和 EntityType 字段的实体。

控制器:

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

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

实体属性:

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

表格:

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

它在 正常 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

不工作 JSON 格式:

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

我在 JSON 示例中做错了什么?

由于您发送 json object 作为请求 body 而不是正常的 POST 字段 - 您应该 json_decode 首先请求内容,然后然后使用 $form->submit(...) 将数据加载到您的表单中。旧的好东西 handleRequest() 在这里不行。看看下面的例子:

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;
}

您也可以使用 FOSRestBundle BodyListener 为您解码 json。为此 - 添加以下配置条目:

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

这仍然不是 $form->handleRequest() 一个好的选择,因为它只允许每个表单使用一种方法,因此如果您将表单配置为执行 POST - PUT 请求将始终失败任何明确的错误消息。

那么你可以这样修改上面的代码:

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;
}

注意你发送的 Content-Type header 就好像它被设置为 'multipart/form-data' 而在其 body 中有 json 有效负载 - 解码器将失败。

只是为了添加到第一个答案,您还需要修改您的 JSON 负载。

你必须直接输入你的 mobile_app_user id :

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