Symfony Form com Doctrine Class Table Inheritance (CTI)

Nov 23 2020

Em uma pergunta anterior , perguntei como lidar com formulários grandes, o resultado foi a Herança de tabela única (STI) ou CTI, mapeamento de herança . Eu escolhi para o CTI.

Agora estou tratando de como criar o formulário com o CTI. Uma rápida visão geral de que tipo ou relação existe.

Cada um inspectionpode ter um ou mais surfaces. Cada superfície é constituído por vários sub entidades, como: surface_leakage, surface_tensionou surface_slope. Como você pode ver surfacetem o CTI com subentidades. Alguns campos se sobrepõem (coloque-os no pai), outros não (coloque-os no filho). Mas no final eu preciso de um formulário com todos os campos agrupados por superfícies e depois por filho (talvez o colapso do Bootrap).

Estabelecer a relação não foi tão difícil, mas usá-la em um formulário é difícil e não tenho certeza de como poderia lidar com isso. Veja o código abaixo com no código dois abordagens

<?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
        //  ...
    }
}

Então, há o formulário 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
    }
}

Espero que alguém possa me ajudar

Respostas

1 Stev Nov 24 2020 at 06:07

Acho que você está procurando formas polimórficas. Verifique este pacotehttps://github.com/infinite-networks/InfiniteFormBundle