Symfony Form with Doctrine Class Table Inheritance (CTI)

最后都变了- 提交于 2020-12-15 05:32:20

问题


In a previous question I ask how to handle large forms, outcome was Single Table Inheritance (STI) or CTI, Inheritance mapping. I've has chosen for CTI.

Now i'm dealing how to create the form with CTI. A quick overview what kind or relation there are.

Each inspection could have one or more surfaces. Each surface consists of many sub entities, like: surface_leakage, surface_tension or surface_slope. As you could see surface has the CTI with sub entities. Some fields overlap (put them in parent), some don't (put them in child). But in the end I need one form with all the fields grouped by surfaces then by child (maybe Bootrap collapse).

Setting up the relation was not that hard, but to use it into a form is difficult and I'm not sure how I could handle this. See below code with in code two approuches

<?php
class Inspection
{
    /**
     * @OneToMany(targetEntity="App\Entity\Surface", mappedBy="inspection")
     */
    protected $surfaces;
}

/**
 * @Entity
 * @InheritanceType("JOINED")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"surface" = "Surface", "surface_leagage" = "SurfaceLeakage", ...})
 */
class Surface
{
    protected $inpection;
    protected $description;
}

class SurfaceLeakage extends Surface
{
    protected $leakageLevel;
}

// .. other child classes (SurfaceTension, SurfaceSlope, ...)

class InspectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // ...

        $builder->add('surfaces', CollectionType::class, [
            'entry_type' => SurfaceType::class,
        ]);
    }
}

// Approach 1, where each child is added to the SurfaceType
// with this approach data should be mapped false
// This approach ensures that I only have to call SurfaceType once and all fields are loaded, but
// could not make this work with data from DB through CIT.
// Also this method does not allow me to add field description (from parent) to all childTypes
class SurfaceType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('leakage', SurfaceLeakageType::class, array('mapped' => false));
        $builder->add('tension', SurfaceTensionType::class, array('mapped' => false));
        //  ...
    }

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

class SurfaceLeakageType extends AbstractType
{

}

// Approach 2, where each childFormType could extend SurfaceType, like below but how to call/create the
// form and handling the data.
// With this approuch i could parent fields to the child
class SurfaceLeakageType extends SurfaceType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('description', TextareaType::class); // field from parent or ...
        parent::buildForm($builder, $options);


        $builder->add('leakageLevel', IntegerType::class); // own field
        //  ...
    }
}

Then there is form inherit_data

// Approach 3, inherit data, now each child should add this as a field like below,
// but how the only thing I'm doing on InspectionType build Surfaces as collection so
// i think inherit data also doesn't work
class SurfaceType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('description', TextareaType::class);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'inherit_data' => true,
        ]);
    }
}

class SurfaceLeakageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // inherit fields
        $builder->add('leakage', SurfaceType::class, [
            'data_class' => SurfaceLeakage::class,
        ]);

        $builder->add('leakageLevel', IntegerType::class); // own field
    }
}

Hope someone could help me out


回答1:


I think you are looking for polymorphic forms. Check this bundle https://github.com/infinite-networks/InfiniteFormBundle



来源:https://stackoverflow.com/questions/64975018/symfony-form-with-doctrine-class-table-inheritance-cti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!