Symfony Form con Doctrine Class Table Inheritance (CTI)

Nov 23 2020

In una domanda precedente ho chiesto come gestire i moduli di grandi dimensioni, il risultato era Single Table Inheritance (STI) o CTI, Inheritance mapping . Ho scelto per CTI.

Ora mi occupo di come creare il modulo con CTI. Una rapida panoramica di che tipo o relazione ci sono.

Ciascuno inspectionpotrebbe averne uno o più surfaces. Ogni superficie è costituita da molte entità sub, come: surface_leakage, surface_tensiono surface_slope. Come puoi vedere surfaceha il CTI con sottoentità. Alcuni campi si sovrappongono (mettili in genitore), altri no (mettili in figlio). Ma alla fine ho bisogno di un modulo con tutti i campi raggruppati per superfici, quindi per figlio (forse Bootrap collassa).

Impostare la relazione non è stato così difficile, ma usarlo in un modulo è difficile e non sono sicuro di come avrei potuto gestirlo. Vedi sotto il codice con nel codice due 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
        //  ...
    }
}

Poi c'è la forma 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
    }
}

Spero che qualcuno possa aiutarmi

Risposte

1 Stev Nov 24 2020 at 06:07

Penso che tu stia cercando forme polimorfiche. Controlla questo pacchettohttps://github.com/infinite-networks/InfiniteFormBundle