表单构建器中的关联数组字段 - Symfony3

8

让我们从背景开始。

我需要一个用户档案,其中包含基本信息,如姓名、电子邮件、电话等。为此,我有一个名为“User”的实体。

我还需要存储问卷调查的答案。我考虑将它们存储在数据库中,作为文本字段中的json格式。这些问题可能会在未来发生变化,目前有大约30个问题,因此我不想将其存储为实体。因此,目前在我的User实体中,我有以下内容:

/**
 * @var array
 *
 * @ORM\Column(name="questionnaire", type="json_array", nullable=true)
 */
private $questionnaire;

我知道Symfony会处理json_encode/json_decode的问题,这很好。但是现在,我在使用Symfony构建器创建表单时遇到了一些问题。起初我以为可以尝试像这样做:
$builder->add('questionnaire[source]');

这个不起作用。对于Symfony大师来说,我知道这很明显 ;o)

所以目前我看到的选择是:CollectionType或Data Transformers。

从我所看到的情况来看,CollectionType将无法使用,因为它只适用于具有一些JS“添加另一行”或类似内容的数字数组字段。http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items 但如果我对此错误,并且我应该使用CollectionType并且有某种神奇的方法,请告诉我。我找不到太多相关信息。

所以我在考虑Data Transformers或者仅在提交时创建一个数组而不使用这个Transformer。使用“mapped => false”创建所有Questionnaire中的字段,然后将这些提交的值设置为关联数组到$questionnaire中。这“感觉”还好,但我不确定如何在“编辑”表单中处理它(从文档中我认为可以使用此 http://symfony.com/doc/current/reference/forms/types/form.html#data)。

问卷本身将有许多ChoiceType字段,一个带有“添加更多行”的CollectionType等等,它将有很多问题。所以它会有点复杂。我想避免为每个问题创建实体作为属性(不确定是否是正确的选择,但考虑到所有情况,我认为这是最好的选择)。
这是我与Symfony的第一次约会,所以任何帮助/提示都会感激。
2个回答

9

几天后,我找到了自己问题的答案。赏金并没有帮助我更快地得到它,但是嘿,有一个解决方案! ;o)

所以事实证明这很简单。我实际上在这个特定问题上没有找到很多信息,所以如果你需要类似的东西,这里就是。

在具有此json_array的实体类中,定义所有所需的键,如下所示:

/**
 * @var array
 *
 * @ORM\Column(name="questionnaire", type="json_array", nullable=true)
 */
private $questionnaire = [
    'favPet'=>'',
    'favFood'=>'',
    'favColor'=>''
];

接下来,在表单构建器中使用"property_path"属性!就这么简单...像这样:https://symfony.com/doc/current/reference/forms/types/form.html#property-path

/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name')
        ->add('email', EmailType::class)
        ->add('phone')
        ->add('address')
         ->add('favPet',TextType::class,[
            'label'=>'Fav pet',
            'property_path'=>'questionnaire[favPet]'
        ])
        ->add('favFood',TextType::class,[
            'label'=>'Fav food',
            'property_path'=>'questionnaire[favFood]'
        ])
        ->add('favColor',TextType::class,[
            'label'=>'Fav color',
            'property_path'=>'questionnaire[favColor]'
        ])
    ;
}

而symfony将处理其余的部分。因为我们使用json_array作为类型,所以symfony将处理json_encode / json_decode的事情。为了让symfony在编辑模式下映射/填充值,该属性必须具有其键定义。否则,您将遇到以下错误:

 

PropertyAccessor需要一个对象或数组图形来操作,但在尝试遍历路径时找到了类型“NULL”

然后在twig模板中可以这样做:

{{ user.questionnaire.favPet }}

就这样啦!:o))

至于JSON或实体(Entity),我知道我没有写实体,但我还没有决定。经过一些IRC对话、阅读和查看https://dev59.com/sm865IYBdhLWcg3wEKKZ#4013207之后,我可能会选择EAV。所以如果你正在考虑JSON与实体(Entity)之间的选择,可以将EAV加入竞争。


0
我曾经在Sylius中遇到过类似的问题:实体有一个名为“configuration”的数组字段,应用程序期望该字段具有以下格式:
['configuration' =>   
        ['filters' =>   
            ['taxons' =>   
                ['frg', 'books']   
            ]   
        ]   
     ];

我已经成功地使用嵌套表单来持久化一个按要求格式化的关联数组:

表单类的层次结构如下:

  • PercentageDiscountConfigurationType - 用于配置
  • ActionFiltersType - 用于过滤器
  • TaxonFilterType - 用于分类

您可以在此处查看具有类似功能的PR: https://github.com/Sylius/Sylius/pull/6054/files


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接