简体   繁体   English

如何使用FOSRest和Symfony表单发布嵌套实体

[英]How to POST nested entities with FOSRest and Symfony Form

Using Symfony 3.2 and FOS REST Bundle I have created some REST endpoints for a resource and use a Symfony Form to define the fields for API DOC. 使用Symfony 3.2和FOS REST Bundle,我为资源创建了一些REST端点,并使用Symfony Form定义了API DOC的字段。 Everything is working fine to this point. 至此一切正常。 Now I'm trying to improve my schema and added a sub entity (one-to-one) to my resource. 现在,我正在尝试改进架构,并向资源中添加一个子实体(一对一)。 I want the main resource to save the sub entity - there is no dedicated endpoint for the sub entity. 我希望主要资源保存子实体-该子实体没有专用的端点。

I followed the instruction on the Symfony documentation and removed all other fields to isolate any issues. 我按照Symfony文档上的说明进行操作,并删除了所有其他字段以隔离任何问题。

This is how my form type looks now: 这是我的表单类型现在的样子:

<?php

namespace VendorName\MyBundle\Form;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CountryType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder
            ->add('mySubEntity', EntityType::class, array(
                'multiple' => false,
                'expanded' => false,
                'property' => 'name',
                'class' => 'MyBundle\Entity\mySubEntity'));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'VendorName\MyBundle\Entity\Country',
            'csrf_protection' => false
        ));
    }

}

Now when I load my api-docs, I receive the error message The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...] 现在,当我加载我的api-docs时,我收到错误消息The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...] The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...] . The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...]

To be honest, I don't even know if adding the Entity to the form is the right approach to make it show up in the API Docs. 老实说,我什至不知道将Entity添加到表单中是否是使它显示在API文档中的正确方法。 Any help in resolving the above issue and / or best practices to achieve this would be appreciated. 解决上述问题和/或实现此问题的最佳做法的任何帮助将不胜感激。

EDIT: Thanks to @miikes this error is now resolved and I can see the api doc showing up correctly with the fields of the nested form. 编辑:感谢@miikes,现在已解决此错误,我可以看到api文档与嵌套表单的字段一起正确显示。 However, now my issue is that the form does not populate the sub entity on the parent entity. 但是,现在我的问题是表单没有在父实体上填充子实体。 This seems to be related to the way I modelled the parent-child relationship and I have posted a new question for this issue . 这似乎与我对父子关系建模的方式有关,并且我为此问题发布了一个新问题

To resolve your error try to use choice_label , instead of property option. 要解决您的错误,请尝试使用choice_label而不是property选项。

'choice_label' => 'name'

But referring to the documentation, EntityType is a kind of ChoiceType , so using this type, you can only select existing entity, not persist new one. 但是,参考文档, EntityTypeChoiceType的一种 ,因此使用此类型,您只能选择现有实体,而不能保留新实体。

The easiest and most clear way for creating new entity instance is creating another type class, designed for your entity, and adding the type as the field to your CountryType . 创建新实体实例的最简单,最清晰的方法是创建另一个为您的实体设计的类型类,并将该类型作为字段添加到CountryType中

class MyEntityType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('some-field', TextType::class)
            ->add('another-field', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => MyEntity::class
        ]);
    }
}

class CountryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('mySubEntity', MyEntityType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Country::class,
            'csrf_protection' => false
        ));
    }
}

So you should pass form data as 因此,您应该将表单数据传递为

['mySubEntity']['some-field'] = 'foo'
['mySubEntity']['another-field'] = 'bar'

Another tip is to use Country::class instead of string 'VendorName\\MyBundle\\Entity\\Country' , because in case of renaming class, IDE refactoring should affect on your type. 另一个技巧是使用Country::class而不是字符串'VendorName\\MyBundle\\Entity\\Country' ,因为在重命名类的情况下,IDE重构会影响您的类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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