【问题标题】:Associative array fields in form builder - Symfony3表单构建器中的关联数组字段 - Symfony3
【发布时间】:2016-09-27 07:03:28
【问题描述】:

让我们从背景开始。

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

我还需要存储问卷中的答案。我正在考虑将它们作为文本字段中的 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 并且有一些神奇的方法请告诉我。我找不到太多关于这个的信息。

所以我在考虑数据转换器,或者只是在提交时创建一个数组,而不需要这个转换器。使用“mapped=>false”创建问卷中的所有字段,然后将这些提交的值设置为 $questionnaire 的关联数组。这“感觉”不错,但我不知道以后如何以“编辑”形式处理这个问题(来自我认为http://symfony.com/doc/current/reference/forms/types/form.html#data 的文档)。

问卷本身会有很多 ChoiceType 字段,一个带有“添加更多行”的 CollectionType 等等,它会有很多问题。所以会有点复杂。我想避免为每个问题创建实体作为属性(不确定这是否是一个正确的选择,但考虑到一切我认为它是最好的选择)。

这是我与 symfony 的第一次约会,所以任何帮助/提示都非常感谢。

【问题讨论】:

    标签: php forms symfony


    【解决方案1】:

    几天后,我找到了自己问题的答案。赏金并没有帮助更快地获得它,但是嘿,有一个解决方案! ;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 }}
    

    就是这样! :o))

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

    【讨论】:

      【解决方案2】:

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

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

      我已经成功地保存了一个关联数组,其格式与使用嵌套表单所请求的一样:

      表单类层次结构是这样的:

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

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

      【讨论】:

        猜你喜欢
        • 2018-07-12
        • 2015-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多