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

时间:2016-05-29 10:40:24

标签: php forms symfony

让我们从背景开始吧。

我需要具有基本信息的用户个人资料,例如姓名,电子邮件,电话等。为此,我有一个实体用户。

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

/**
 * @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的关联数组。这"感觉"好的,但是我不确定如何在以后编辑#34;编辑"表格(来自我认为使用此http://symfony.com/doc/current/reference/forms/types/form.html#data)的文档。

调查表本身将有许多ChoiceType字段,一个CollectionType为"添加更多行"等等,它会有很多问题。所以它会有点复杂。我想避免为每个问题作为财产创建实体(不确定它是否是正确的选择,但考虑到我认为它是最好的一切)。

这是我与symfony的第一次约会,所以任何帮助/小贴士都会欣赏。

2 个答案:

答案 0 :(得分:7)

几天后,我找到了自己的问题的答案。赏金没有帮助它更快,但嘿,有一个解决方案! ; 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"在尝试遍历路径时

然后在树枝模板中你可以这样做:

{{ user.questionnaire.favPet }}

那就是它! :○))

至于JSON或实体。我知道我没有写任何实体,但我没有下定决心。经过一些IRC对话,阅读和https://stackoverflow.com/a/4013207/531099我可能会选择EAV。因此,如果您在JSON与实体之间做出决定,请将EAV添加到竞赛中。

答案 1 :(得分:0)

我遇到了与Sylius类似的问题:该实体有一个名为“configuration”的数组字段,该应用程序希望该字段的格式如下:

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

我设法通过使用嵌套表单来保持一个格式化的关联数组:

表单类层次结构如下:

  • PercentageDiscountConfigurationType - 用于配置
  • ActionFiltersType - 适用于过滤器
  • TaxonFilterType - for taxons

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