Php Symfony 3.4表单EntityType所选值为空

Php Symfony 3.4表单EntityType所选值为空,php,symfony,twig,symfony-3.4,Php,Symfony,Twig,Symfony 3.4,我对Symfony 3.4 EntityType有问题 CategoryType.php class CategoryType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('title') ->add('spec', Col

我对Symfony 3.4 EntityType有问题

CategoryType.php

class CategoryType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('spec', CollectionType::class, [
                'entry_type' => SpecificationType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'label' => false,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Category::class,
        ));
    }
}
class SpecificationType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title', EntityType::class, [
            'class' => Specification::class,
            'label' => false,
        ]);
    }

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

    public function getBlockPrefix()
    {
        return 'specification';
    }
}
{{ form_widget(form.title) }}
{{ form_widget(form.spec) }}
/**
 * @ORM\ManyToMany(targetEntity="Specification", inversedBy="categoryList")
 * @ORM\JoinTable(name="category_specification")
 */
private $spec;
SpecificationType.php

class CategoryType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('spec', CollectionType::class, [
                'entry_type' => SpecificationType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'label' => false,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Category::class,
        ));
    }
}
class SpecificationType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title', EntityType::class, [
            'class' => Specification::class,
            'label' => false,
        ]);
    }

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

    public function getBlockPrefix()
    {
        return 'specification';
    }
}
{{ form_widget(form.title) }}
{{ form_widget(form.spec) }}
/**
 * @ORM\ManyToMany(targetEntity="Specification", inversedBy="categoryList")
 * @ORM\JoinTable(name="category_specification")
 */
private $spec;
表单按预期呈现:标题为文本字段,2个选择元素。但问题是渲染选择元素并没有选择选定值

form.html.twig

class CategoryType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('spec', CollectionType::class, [
                'entry_type' => SpecificationType::class,
                'allow_add' => true,
                'allow_delete' => true,
                'label' => false,
            ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Category::class,
        ));
    }
}
class SpecificationType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title', EntityType::class, [
            'class' => Specification::class,
            'label' => false,
        ]);
    }

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

    public function getBlockPrefix()
    {
        return 'specification';
    }
}
{{ form_widget(form.title) }}
{{ form_widget(form.spec) }}
/**
 * @ORM\ManyToMany(targetEntity="Specification", inversedBy="categoryList")
 * @ORM\JoinTable(name="category_specification")
 */
private $spec;
结果

预期结果

当在
SpecificationType.php
EntityType::class
中被替换为
TextField:class
时,现在表单呈现的不是2个选择元素,而是2个文本输入(预期行为),分配的值正确:

我开始挖掘这些select元素最初是如何呈现的,发现这个block
{%-block choice\u widget\u options-%}
负责呈现select元素

在这个区块内是代码的和平:

<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>
找到了解决办法

正如@Nickolaus所写的:

[…]您遇到了这个问题,因为在您的实现中它是一个复合表单,没有简单的表单,而且symfony无法解析在子表单中创建的哪个字段需要用作实体字段的源

因此,解决方案是:

重构
SpecificationType.php
如下:

class SpecificationType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'class' => Specification::class,
            'label' => false,
        ));
    }

    public function getParent()
    {
        return EntityType::class;
    }

    public function getBlockPrefix()
    {
        return 'specification';
    }
}
使用
getParent()
方法,将所有字段配置移动到
configureOptions
并删除
buildForm()
方法


最后。。浪费了这么多时间。

您能展示一下
spec
属性是如何在
Category
实体中定义的吗?@Djengobarm请查看更新部分。