如何 POST 使用 FOSRest 和 Symfony Form 嵌套实体
How to POST nested entities with FOSRest and Symfony Form
我使用 Symfony 3.2 和 FOS REST Bundle 为资源创建了一些 REST 端点,并使用 Symfony 表单定义 API DOC 的字段。到目前为止一切正常。
现在我正在尝试改进我的模式并向我的资源添加一个子实体(一对一)。我希望主要资源保存子实体 - 子实体没有专用端点。
我按照 the Symfony documentation 上的说明删除了所有其他字段以隔离任何问题。
这是我的表单类型现在的样子:
<?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
));
}
}
现在,当我加载我的 api-docs 时,我收到错误消息 The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...]
。
老实说,我什至不知道将实体添加到表单是否是使其显示在 API 文档中的正确方法。任何解决上述问题的帮助和/或实现此目的的最佳实践将不胜感激。
编辑: 感谢@miikes,这个错误现在已经解决,我可以看到 api 文档正确显示了嵌套表单的字段。但是,现在我的问题是表单不会填充父实体上的子实体。这似乎与我对亲子关系的建模方式有关,我发布了一个。
要解决您的错误,请尝试使用 choice_label
,而不是 property
选项。
'choice_label' => 'name'
但是参考文档,EntityType is a kind of ChoiceType,所以使用这种类型,你只能select现有实体,不能持久化新实体。
创建新实体实例的最简单和最清晰的方法是创建另一个类型 class,专为您的实体设计,并将该类型作为字段添加到您的 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
));
}
}
所以你应该将表单数据作为
['mySubEntity']['some-field'] = 'foo'
['mySubEntity']['another-field'] = 'bar'
另一个提示是使用 Country::class
而不是字符串 'VendorName\MyBundle\Entity\Country'
,因为在重命名 class 的情况下,IDE 重构应该会影响您的类型。
我使用 Symfony 3.2 和 FOS REST Bundle 为资源创建了一些 REST 端点,并使用 Symfony 表单定义 API DOC 的字段。到目前为止一切正常。 现在我正在尝试改进我的模式并向我的资源添加一个子实体(一对一)。我希望主要资源保存子实体 - 子实体没有专用端点。
我按照 the Symfony documentation 上的说明删除了所有其他字段以隔离任何问题。
这是我的表单类型现在的样子:
<?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
));
}
}
现在,当我加载我的 api-docs 时,我收到错误消息 The option "property" does not exist. Defined options are: "action", "allow_extra_fields", [...]
。
老实说,我什至不知道将实体添加到表单是否是使其显示在 API 文档中的正确方法。任何解决上述问题的帮助和/或实现此目的的最佳实践将不胜感激。
编辑: 感谢@miikes,这个错误现在已经解决,我可以看到 api 文档正确显示了嵌套表单的字段。但是,现在我的问题是表单不会填充父实体上的子实体。这似乎与我对亲子关系的建模方式有关,我发布了一个
要解决您的错误,请尝试使用 choice_label
,而不是 property
选项。
'choice_label' => 'name'
但是参考文档,EntityType is a kind of ChoiceType,所以使用这种类型,你只能select现有实体,不能持久化新实体。
创建新实体实例的最简单和最清晰的方法是创建另一个类型 class,专为您的实体设计,并将该类型作为字段添加到您的 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
));
}
}
所以你应该将表单数据作为
['mySubEntity']['some-field'] = 'foo'
['mySubEntity']['another-field'] = 'bar'
另一个提示是使用 Country::class
而不是字符串 'VendorName\MyBundle\Entity\Country'
,因为在重命名 class 的情况下,IDE 重构应该会影响您的类型。