简体   繁体   English

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

[英]Associative array fields in form builder - Symfony3

Let's start with a background. 让我们从背景开始。

I need user profile that will have basic info like name, email, phone etc. And for that I have an entity User. 我需要具有基本信息的用户个人资料,如姓名,电子邮件,电话等。为此,我有一个实体用户。

I also need to store answers from a questionnaire. 我还需要存储调查问卷的答案。 I was thinking to store them in database as a json in a text field. 我想将它们作为文本字段中的json存储在数据库中。 Those questions can change in the future, there are currently ~30 questions so I don't want to store it as an entity. 这些问题将来可能会发生变化,目前有大约30个问题,所以我不想将其存储为实体。 So currently in my User entity I have this: 所以目前在我的用户实体中我有这个:

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

I understand that Symfony will take care of json_encode/json_decode thing. 我知道Symfony会处理json_encode / json_decode的事情。 So this is great. 所以这很棒。

But now, I have a bit of problem with creating a form with the symfony builder. 但是现在,我在使用symfony构建器创建表单时遇到了一些问题。

First I thought I could try something like this: 首先,我想我可以尝试这样的事情:

$builder->add('questionnaire[source]');

Which doesn't work. 哪个不起作用。 For symfony masters it's obvious I know ;o) 对于symfony大师来说,我知道这很明显; o)

So currently my choices I see are: CollectionType or Data Transformers. 所以我目前的选择是:CollectionType或Data Transformers。

From what I see, CollectionType will not work, as it's only work with numeric arrays where we have field with some JS "Add another row" or something. 从我看到,CollectionType将无法工作,因为它只适用于数字数组,其中我们有一些JS“添加另一行”或其他东西。 http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items But if I'm wrong about this and I should go with CollectionType and there is some magic way please tell me. http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items但如果我对此错了,我应该选择CollectionType并且有一些神奇的方法请告诉我。 I can't find much about this. 我找不到这个。

So I was thinking Data Transformers or simply creating an array on submit without this Transformer thing. 所以我在考虑使用Data Transformers或者只是在没有这个Transformer的情况下在提交时创建一个数组。 Create all fields that are in Questionnaire with the "mapped=>false" and then set those submitted values as an associative array to $questionnaire. 使用“mapped => false”创建问卷调查中的所有字段,然后将这些提交的值设置为$ questionnaire的关联数组。 This "feels" ok, but I'm not sure how to later handle this in "Edit" form (from docs I think with this http://symfony.com/doc/current/reference/forms/types/form.html#data ). 这种“感觉”还可以,但我不知道如何在“编辑”表单中处理这个问题(从我想到的文档http://symfony.com/doc/current/reference/forms/types/form.html #data )。

Questionnaire itself will have many ChoiceType fields, a CollectionType with "Add more row" and so on and it will have lots of questions. 问卷调查本身将有许多ChoiceType字段,一个CollectionType与“添加更多行”等等,它将有很多问题。 So it will be a bit complex. 所以它会有点复杂。 I would like to avoid creating entity for that with each question as a property (not sure if it's a right choice, but considering everything I believe it's the best one). 我想避免为每个问题作为一个属性创建实体(不确定它是否是一个正确的选择,但考虑到我认为它是最好的一切)。

This is my first date with symfony so any help/tips appreciate. 这是我与symfony的第一次约会,所以任何帮助/小贴士都会欣赏。

After few days I found the answer for my own question. 几天后,我找到了自己问题的答案。 Bounty didn't helped to get it faster, but hey, there is a solution! Bounty没有帮助它更快,但嘿,有一个解决方案! ;o) ; O)

So turns out it's really simple. 事实证明它非常简单。 I've actually didn't found a lot on this particular problem, so in case you need something similar, here it is. 我实际上并没有在这个特定的问题上找到很多东西,所以如果你需要类似的东西,这里就是。

In the entity class with this json_array, define all needed keys like so: 在具有此json_array的实体类中,定义所有需要的键,如下所示:

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

Next, in the form builder use the "property_path"! 接下来,在表单构建器中使用“property_path”! It's that simple... https://symfony.com/doc/current/reference/forms/types/form.html#property-path like this: 就这么简单...... 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]'
        ])
    ;
}

And symfony will handle the rest. 而symfony将处理剩下的事情。 Because we used json_array as a type, symfony will handle json_encode/json_decode thing. 因为我们使用json_array作为类型,symfony将处理json_encode / json_decode的事情。 In order for symfony to map/populate values in edit mode the property must have it's key defined. 为了使symfony在编辑模式下映射/填充值,属性必须定义它的键。 Otherwise you will get error: 否则你会收到错误:

PropertyAccessor requires a graph of objects or arrays to operate on, but it found type "NULL" while trying to traverse path PropertyAccessor需要对象或数组的图形进行操作,但在尝试遍历路径时发现类型为“NULL”

And then in the twig template you can do this: 然后在twig模板中你可以这样做:

{{ user.questionnaire.favPet }}

And that's it! 就是这样! :o)) :O))

As for the JSON or Entity. 至于JSON或实体。 I know I wrote no entity, but I didn't made up my mind. 我知道我没有写任何实体,但我没有下定决心。 After some IRC conversations, reading and this https://stackoverflow.com/a/4013207/531099 I will probably go with EAV. 经过一些IRC对话,阅读和https://stackoverflow.com/a/4013207/531099我可能会选择EAV。 So if you are deciding between JSON vs Entity, add EAV to the race. 因此,如果您在JSON与实体之间做出决定,请将EAV添加到比赛中。

I had a similar problem with Sylius: the entity had an array field called "configuration" and that field could was expected by the app to have the format like this: 我和Sylius有类似的问题:该实体有一个名为“configuration”的数组字段,该应用程序可能希望该字段的格式如下:

['configuration' =>   
        ['filters' =>   
            ['taxons' =>   
                ['frg', 'books']   
            ]   
        ]   
     ];

I have managed to persist an associative array formatted like it was requested by using nested forms: 我设法保持一个关联数组的格式,就像使用嵌套表单请求一样:

The form class hierarchy is this: 表单类层次结构如下:

  • PercentageDiscountConfigurationType - for configuration PercentageDiscountConfigurationType - 用于配置
  • ActionFiltersType - for filters ActionFiltersType - 用于过滤器
  • TaxonFilterType - for taxons TaxonFilterType - 用于分类

You can see a PR with a similar functionality here: https://github.com/Sylius/Sylius/pull/6054/files 您可以在这里看到具有类似功能的PR: https//github.com/Sylius/Sylius/pull/6054/files

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

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