级联manytomany关系symfony插入和编辑

时间:2017-10-16 22:18:08

标签: symfony-2.8

我在这里寻求你的帮助,我希望我能找到一些帮助 我有一个多层次的关系,我想插入objectif 我在partenaire indicur之间有很多东西, 在指示和安妮之间的许多人 和反对之间的关​​系

这意味着一个partenaire可以有许多物体,每个物体都是一个反对和一个反复的腹部来指示

这是我对树枝的看法

public function AjouterPartenaireAction(Request $request) {
    $partenaire = new Partenaire();
    $form = $this->createForm('ApfeBundle\Form\PartenaireType', $partenaire);
    $form->handleRequest($request);
    $indicateures=$request->get('indicateur');
    $annees=$request->get('annee');
    $objectifs=$request->get('objectif');
    $em = $this->getDoctrine()->getManager();
    foreach ($indicateures as $indicateur) {
        $indicateure     = $em->getRepository('ApfeBundle:Indicateure')->findOneById($indicateur);
        foreach ($annees as $annee) {
            $annee = $em->getRepository('ApfeBundle:Annee')->findOneById($annee);
            $annee->addIndicateure($indicateure);
            $em->persist($annee);
            $em->flush();
        }
        $partenaire->addIndicateure($indicateure);
    }
    $em->persist($partenaire);
    $em->flush();
    $mi = new \MultipleIterator();
    $mi->attachIterator(new \ArrayIterator($annees));
    $mi->attachIterator(new \ArrayIterator($objectifs));
    $mi->attachIterator(new \ArrayIterator($indicateures));
    foreach ($mi as $value) {
        $annees =  $value[0];
        $objectif = $value[1];
        $idindicateur = $value[2];
        $em1 = $this->getDoctrine()->getManager();
        $indicateure     = $em->getRepository('ApfeBundle:Indicateure')->findOneById($idindicateur);
        $annee     = $em->getRepository('ApfeBundle:Annee')->findOneById($annees);

        $obejctif = new Objectif();
        $obejctif->setAnneeId($annee);
        $obejctif->setObjectif($objectif);
        $obejctif->setPartenaireId($partenaire);
        $obejctif->setIndicateureId($indicateure);
        $em1->persist($obejctif);
        $em1->flush();
    }

    $form = $this->createForm(new PartenaireType(), $partenaire);
    $form->handleRequest($request);
    $em = $this->getDoctrine()->getManager();
    $idpartenaire = $partenaire->getId();
    $partenaires = $em->getRepository('ApfeBundle:Partenaire')->findAll();
    return $this->container->get('templating')->renderResponse('partenaire/new.html.twig', array(
        'idpartenaire' => $idpartenaire,
        'partenaires' => $partenaires,
    ));
}

这是我在控制器中插入的动作

{{1}}

问题是当我提交它并没有正确插入所有我的entreies  因为它出现在下面的图片中

有人可以帮忙,谢谢你

insertion in the view

my table database

1 个答案:

答案 0 :(得分:0)

确定。这将是一篇很长的帖子。对不起。

以下是我如何复制您的问题。

首先创建实体。我正在使用yml,所以如果使用注释,那么将yml样式转换为注释样式将是你的工作。

//AppBundle/Resource/config/doctrine/Annee.orm.yml
AppBundle\Entity\Annee:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\AnneeRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    manyToMany:
        indicateurs:
            targetEntity: AppBundle\Entity\Indicateur
            mappedBy: annees
            cascade: ['persist']
            fetch: EAGER
    oneToMany:
        objectifes:
            targetEntity: AppBundle\Entity\Objectif
            mappedBy: annee
            cascade: ['persist', 'remove']
            orphanRemoval: true
            nullable: true
    fields:
        name:
            type: string
            length: 255
    lifecycleCallbacks: {  }


//AppBundle/Resource/config/doctrine/Indicateur.orm.yml
    AppBundle\Entity\Indicateur:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\IndicateurRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    manyToMany:
        annees:
            targetEntity: AppBundle\Entity\Annee
            inversedBy: indicateurs
            joinTable:
                name: annees_indicateurs
                joinColumns:
                    indicateur_id:
                        referencedColumnName: id
                inverseJoinColumns:
                    annee_id:
                        referencedColumnName: id
            cascade: ['persist', 'remove']
            fetch: EAGER
        partenaires:
            targetEntity: AppBundle\Entity\Partenaire
            mappedBy: indicateurs
            cascade: ['persist']
            fetch: EAGER
    fields:
        name:
            type: string
            length: 255
    lifecycleCallbacks: {  }


//AppBundle/Resources/config/doctrine/Objectif.orm.yml
AppBundle\Entity\Objectif:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\ObjectifRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    manyToOne:
        annee:
            targetEntity: AppBundle\Entity\Annee
            inversedBy: objectifes
            joinColumn:
                name: annee_id
                referencedColumnName: id
            cascade: ['persist']
    fields:
        name:
            type: string
            length: 255
    lifecycleCallbacks: {  }


//AppBundle/Resources/config/doctrine/Partenaire.orm.yml
AppBundle\Entity\Partenaire:
    type: entity
    table: null
    repositoryClass: AppBundle\Repository\PartenaireRepository
    id:
        id:
            type: integer
            id: true
            generator:
                strategy: AUTO
    manyToMany:
        indicateurs:
            targetEntity: AppBundle\Entity\Indicateur
            inversedBy: partenaires
            joinTable:
                name: indicateurs_partenaires
                joinColumns:
                    partenaire_id:
                        referencedColumnName: id
                inverseJoinColumns:
                    indicateur_id:
                        referencedColumnName: id
            cascade: ['persist', 'remove']
            fetch: EAGER
    fields:
        name:
            type: string
            length: 255
    lifecycleCallbacks: {  }

下一步是设置学说的方法。这些将在内部用于采取行动。

//AppBundle/Entity/Annee.php
//pay attention to the way addIndicateur(), removeIndicateur() methods are wrote. They are essential so that the many-to-many between Annee and Indicateur entities to work. The same for Indicateur.php and Partenaire.php
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Annee
 */
class Annee
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $objectifes;

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $indicateurs;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->objectifes = new \Doctrine\Common\Collections\ArrayCollection();
        $this->indicateurs = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Annee
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
    */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Add objectife
     *
     * @param \AppBundle\Entity\Objectif $objectife
     * @return Annee
     */
    public function addObjectife(\AppBundle\Entity\Objectif $objectife)
    {
        $this->objectifes[] = $objectife;

        return $this;
    }

    /**
     * Remove objectife
     *
     * @param \AppBundle\Entity\Objectif $objectife
     */
    public function removeObjectife(\AppBundle\Entity\Objectif $objectife)
    {
        $this->objectifes->removeElement($objectife);
    }

    /**
     * Get objectifes
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getObjectifes()
    {
        return $this->objectifes;
    }

    /**
     * Add indicateur
     *
     * @param \AppBundle\Entity\Indicateur $indicateur
     * @return Annee
     */
    public function addIndicateur(\AppBundle\Entity\Indicateur $indicateur)
    {
        if ($this->indicateurs->contains($indicateur)) {
            return;
        }

        $this->indicateurs[] = $indicateur;
        $indicateur->addAnnee($this);

        return $this;
    }

    /**
     * Remove indicateur
     *
     * @param \AppBundle\Entity\Indicateur $indicateur
     */
    public function removeIndicateur(\AppBundle\Entity\Indicateur $indicateur)
    {
        if (!$this->indicateurs->contains($indicateur)) {
            return;
        }

        $this->indicateurs->removeElement($indicateur);
        $indicateur->removeAnnee($this);
    }

    /**
     * Get indicateurs
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getIndicateurs()
    {
        return $this->indicateurs;
    }
}



//AppBundle/Entity/Indicateur.php
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Indicateur
 */
class Indicateur
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Indicateur
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $annees;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->annees = new \Doctrine\Common\Collections\ArrayCollection();
        $this->partenaires = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add annee
     *
     * @param \AppBundle\Entity\Annee $annee
     * @return Indicateur
     */
    public function addAnnee(\AppBundle\Entity\Annee $annee)
    {
        if ($this->annees->contains($annee)) {
            return;
        }

        $this->annees[] = $annee;
        $annee->addIndicateur($this);

        return $this;
    }

    /**
     * Remove annee
     *
     * @param \AppBundle\Entity\Annee $annee
     */
    public function removeAnnee(\AppBundle\Entity\Annee $annee)
    {
        if (!$this->annees->contains($annee)) {
            return;
        }

        $this->annees->removeElement($annee);
        $annee->removeIndicateur($this);
    }

    /**
     * Get annees
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getAnnees()
    {
        return $this->annees;
    }

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $partenaires;

    /**
     * Add partenaire
     *
     * @param \AppBundle\Entity\Partenaire $partenaire
     * @return Indicateur
     */
    public function addPartenaire(\AppBundle\Entity\Partenaire $partenaire)
    {
        if ($this->partenaires->contains($partenaire)) {
            return;
        }

        $this->partenaires[] = $partenaire;
        $partenaire->addIndicateur($this);

        return $this;
    }

    /**
     * Remove partenaire
     *
     * @param \AppBundle\Entity\Partenaire $partenaire
     */
    public function removePartenaire(\AppBundle\Entity\Partenaire $partenaire)
    {
        if (!$this->partenaires->contains($partenaire)) {
            return;
        }

        $this->partenaires->removeElement($partenaire);
        $partenaire->removeIndicateur($this);
    }

    /**
     * Get partenaires
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getPartenaires()
    {
        return $this->partenaires;
    }
}



//AppBundle/Entity/Objectif.php
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Objectif
 */
class Objectif
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Objectif
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @var \AppBundle\Entity\Annee
     */
    private $annee;

    /**
     * Set annee
     *
     * @param \AppBundle\Entity\Annee $annee
     * @return Objectif
     */
    public function setAnnee(\AppBundle\Entity\Annee $annee = null)
    {
        $this->annee = $annee;

        return $this;
    }

    /**
     * Get annee
     *
     * @return \AppBundle\Entity\Annee 
     */
    public function getAnnee()
    {
        return $this->annee;
    }
}



//AppBundle/Entity/Partenaire.php
<?php

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Partenaire
 */
class Partenaire
{
    /**
     * @var int
     */
    private $id;

    /**
     * @var string
     */
    private $name;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Partenaire
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string 
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $indicateurs;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->indicateurs = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add indicateur
     *
     * @param \AppBundle\Entity\Indicateur $indicateur
     * @return Partenaire
     */
    public function addIndicateur(\AppBundle\Entity\Indicateur $indicateur)
    {
        if ($this->indicateurs->contains($indicateur)) {
            return;
        }

        $this->indicateurs[] = $indicateur;
        $indicateur->addPartenaire($this);

        return $this;
    }

    /**
     * Remove indicateur
     *
     * @param \AppBundle\Entity\Indicateur $indicateur
     */
    public function removeIndicateur(\AppBundle\Entity\Indicateur $indicateur)
    {
        if (!$this->indicateurs->contains($indicateur)) {
            return;
        }

        $this->indicateurs->removeElement($indicateur);
        $indicateur->removePartenaire($this);
    }

    /**
     * Get indicateurs
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getIndicateurs()
    {
        return $this->indicateurs;
    }
}

接下来是表格(Type)。我为每个实体使用php app/console doctrine:generate:crud,并将结果表单更改为:

//AppBundle/Form/AnneeType.php
<?php

namespace AppBundle\Form;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AnneeType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('indicateurs', EntityType::class, [
                'class' => 'AppBundle:Indicateur',
                'placeholder' => 'Choose an Indicateur',
                'choice_label' => function($indicateurs) {
                    return $indicateurs->getName();
                },
                'multiple' => true,
                'expanded' => false,
                'by_reference' => false,
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Annee'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_annee';
    }
}




//AppBundle/Form/IndicateurType.php
<?php

namespace AppBundle\Form;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class IndicateurType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('partenaires', EntityType::class, [
                'class' => 'AppBundle:Partenaire',
                'placeholder' => 'Choose a Partenaire',
                'choice_label' => function($partenaire) {
                    return $partenaire->getName();
                },
                'multiple' => true,
                'expanded' => false,
                'by_reference' => false,
            ])
            ->add('annees', EntityType::class, [
                'class' => 'AppBundle:Annee',
                'placeholder' => 'Choose an Annee',
                'choice_label' => function($annee) {
                    return $annee->getName();
                },
                'multiple' => true,
                'expanded' => false,
                'by_reference' => false,
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Indicateur'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_indicateur';
    }
}




//AppBundle/Form/ObjectifType.php
<?php

namespace AppBundle\Form;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ObjectifType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('annee', EntityType::class, [
                'class' => 'AppBundle:Annee',
                'placeholder' => 'Select Annee',
                'choice_label' => function($annee) {
                    return $annee->getName();
                },
                'multiple' => false,
                'expanded' => false
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Objectif'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_objectif';
    }
}





//AppBundle/Form/PartenaireType.php
<?php

namespace AppBundle\Form;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PartenaireType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
            ->add('indicateurs', EntityType::class, [
                'class' => 'AppBundle:Indicateur',
                'placeholder' => 'Choose an Indicateur',
                'choice_label' => function($indicateur) {
                    return $indicateur->getName();
                },
                'multiple' => true,
                'expanded' => false,
                'by_reference' => false,
            ])
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Partenaire'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_partenaire';
    }
}

对于渲染,我使用了默认的crud表单,添加了novalidate属性(适用于所有表单):

{{ form_start(form,{attr:{'novalidate':'novalidate'}}) }}

我使用了默认的CRUD控制器和路由。如果您在为每个实体创建CRUD时使用yaml,那么您需要将主routing.yml文件导入app/config/routing.yml

crud:
    resource: '@AppBundle/Resources/config/routing.yml'

否则,如果您正在使用注释,那么您已完成所有设置。