以 Symfony4 形式将实体对象值传递给嵌套的 CollectionTypes

Passing Entity object value in to nested CollectionTypes in a Symfony4 form

概述:在 Products VariantSets 中 Foreach VariantGroup 我需要创建一个包含 VariantGroups Variants 在 Symfony 形式中

详情: 我有一个 Product 实体,它作为 ManyToMany 关系关联到多个 VariantSet 对象。 VariantSet 对象包含多个 VariantGroup 对象,每个对象都需要生成一个下拉列表以显示其 Variant 个选项。

对于嵌套 CollectionTypes,我只需要使与父 CollectionType 相关的选项可访问。

因此,唯一可用的 Variants 应该与 VariantGroups 相关,而这些 VariantGroups 仅与可用的 VariantSets 相关,而这些 VariantSets 与最初解析的 Product 相关联.

有一些信息指出使用查询生成器仅获取相关项目,但我想知道这是否是最佳做法。另外 - 我如何传递以前的表格(因此在 VariantGroup 的嵌套 CollectionType 中获得顶级 Product,因为 VariantSets 位于这两者之间。

这甚至有可能在 Symfony 表单中使用最佳实践来实现吗?

所需输出示例 here

是的。答案是嵌套的 CollectionType 表单和最终表单中的自定义查询构建器(出于某种原因,它调用了数据库中的所有 Variant 对象,而不是使用与已解析的 VariantGroup 对象:

主要产品形态

class ComplexProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        // Render the variant sets based on the parsed product
        $builder
            ->add('variantSets', CollectionType::class, [
                'entry_type' => VariantSetComplexProductType::class,
                'label'=> false,
                'by_reference' => true,


            ] );
        ;
    }


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

}

渲染产品变体集: (以获得与主要产品 VarianSet 对象关联的正确 VariantGroups

class VariantSetComplexProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        // Render the groups based on the Variant sets
        $builder
            ->add( 'label' )
            ->add( 'variantGroups', CollectionType::class, [
                'entry_type' => VariantGroupComplexProductType::class,
                'label'=> false,
                'by_reference' => true
            ] )
        ;
    }


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

在下拉列表中渲染变量集 VariantGroups 及其 Variants

Variant 对象的下拉需要使用 query_builder 选项在 FromEvent 中完成,否则我会遇到所有 Variant 对象的问题在数据库中被调用。

需要进行检查以确保根据已解析的 VariantGroup.

只调用了正确的 Variant 对象
class VariantGroupComplexProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        // Render the drop downs based on the Parsed variant group
        $builder
            ->add( 'label' )
            // Rendering of the drop down must be done after the previous form data is available
            ->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'preSetData']);
        ;
    }


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

    public function preSetData(FormEvent $event)
    {
        $form = $event->getForm();

        /** @var VariantGroup $child */
        $child = $event->getData();


        $form
            ->add('variants', EntityType::class, array(
                'class' => Variant::class,
                'by_reference' => true,
                'query_builder' => function (EntityRepository $er) use ( $child ) {
                    return $er->createQueryBuilder('u')
                        ->where('u.variant_group = :variant_group')
                        ->setParameter('variant_group', $child )
                        ->orderBy('u.label', 'DESC');
                },
'choice_label' => 'label',
            ));

    }
}