如何在Symfony 2中集成多个实体


How to integrate multiple entity in form in Symfony 2

我正在Symfony 2的表单上工作,我需要一些帮助。该表单用于修改有关项目的信息。我有两个实体,项目(一个项目)和projetInt(所有需要国际化的文本)。我做了一个项目类型的形式,它工作得很好。

问题来了,当我需要有projetInt形式内部的项目形式。起初,我试图使用一个集合字段,但我遇到了一个奇怪的错误,我还没有解决(https://stackoverflow.com/questions/31397195/error-with-the-collection-field-in-form-in-symfony-2)。

事情是,我想要的是projetInt形式被添加两次在项目形式内,因为我的项目的文本必须在法语和英语两种可用。另一件事是,我希望这个表单可以用于我的添加项目操作,因为如果我想修改我的项目,我只需要将项目传递给表单,因为在这两种情况下,添加或修改,必要的字段或完全相同。

这是我到目前为止得到的:

我的项目实体:

<?php
namespace PublicBundle'Entity;
use Doctrine'Common'Collections'ArrayCollection;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'HttpFoundation'File'UploadedFile;
use Symfony'Component'Validator'Constraints as Assert;
/**
 * Projet
 *
 * @ORM'Table(name="pt_projet");
 * @ORM'Entity
 * @ORM'Entity(repositoryClass="PublicBundle'Entity'ProjetDepot")
 * @ORM'HasLifecycleCallbacks
 */
class Projet
{
    /**
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    //ID du projet
    protected $id;
     /**
     * @ORM'OneToMany(targetEntity="ProjetInt", mappedBy="projet", orphanRemoval=true)
     */
    protected $descriptions;
    /**
     * @ORM'Column(name="pro_img", type="string", length=64, unique=true)
     */
    //Nom du fichier de l'image du projet
    protected $image;
    private $imageTemp;
    /**
     * @ORM'Column(name="pro_technologie_utilisee", type="text", length=200)
     */
    //Text qui liste tout les technologies utilisées pour le projet
    protected $technologie;
    /**
     * @ORM'Column(name="pro_annee", type="integer", length=4)
     */
    //Année de réalisation du projet
    protected $annee;
    /**
     * @ORM'ManyToOne(targetEntity="Type", inversedBy="projets")
     * @ORM'JoinColumn(name="pro_type", referencedColumnName="id", nullable=false)
     */
    //Clef étrangère du type de projet
    //Le type de projet ne correspond pas à la catégore. Il peu être Unity, flash, image, vidéo, etc. Il permet de savoir quelle page charger pour pouvoir intégrer le projet dans le portfolio.
    protected $type;
    /**
     * @ORM'Column(name="pro_fichier", type="string", length=64, unique=true)
     */
    //Nom du fichier du projet
    private $fichier;
    private $fichierTemp;
    /**
     * @ORM'Column(name="pro_largeur", type="integer")
     */
    //Largeur du projet
    protected $largeur;
    /**
     * @ORM'Column(name="pro_hauteur", type="integer")
     */
    //Hauteur du projet
    protected $hauteur;
    /**
    * @ORM'ManyToMany(targetEntity="Categorie", cascade={"persist"})
    */
    //La ou les catégories du projet
    private $categories;
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->descriptions=new ArrayCollection();
        $this->categories=new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set image
     *
     * @param string $image
     * @return Projet
     */
    public function setImage($image)
    {
        $this->image = $image;
        return $this;
    }
    /**
     * Get image
     *
     * @return string 
     */
    public function getImage()
    {
        return $this->image;
    }
    /**
     * Set technologie
     *
     * @param string $technologie
     * @return Projet
     */
    public function setTechnologie($technologie)
    {
        $this->technologie = $technologie;
        return $this;
    }
    /**
     * Get technologie
     *
     * @return string 
     */
    public function getTechnologie()
    {
        return $this->technologie;
    }
    /**
     * Set annee
     *
     * @param integer $annee
     * @return Projet
     */
    public function setAnnee($annee)
    {
        $this->annee = $annee;
        return $this;
    }
    /**
     * Get annee
     *
     * @return integer 
     */
    public function getAnnee()
    {
        return $this->annee;
    }
    /**
     * Set fichier
     *
     * @param string $fichier
     * @return Projet
     */
    public function setFichier($fichier)
    {
        $this->fichier = $fichier;
        return $this;
    }
    /**
     * Get fichier
     *
     * @return string 
     */
    public function getFichier()
    {
        return $this->fichier;
    }
    /**
     * Set largeur
     *
     * @param integer $largeur
     * @return Projet
     */
    public function setLargeur($largeur)
    {
        $this->largeur = $largeur;
        return $this;
    }
    /**
     * Get largeur
     *
     * @return integer 
     */
    public function getLargeur()
    {
        return $this->largeur;
    }
    /**
     * Set hauteur
     *
     * @param integer $hauteur
     * @return Projet
     */
    public function setHauteur($hauteur)
    {
        $this->hauteur = $hauteur;
        return $this;
    }
    /**
     * Get hauteur
     *
     * @return integer 
     */
    public function getHauteur()
    {
        return $this->hauteur;
    }
    /**
     * Add descriptions
     *
     * @param 'PublicBundle'Entity'ProjetInt $descriptions
     * @return Projet
     */
    public function addDescription('PublicBundle'Entity'ProjetInt $descriptions)
    {
        $this->descriptions[] = $descriptions;
        return $this;
    }
    /**
     * Remove descriptions
     *
     * @param 'PublicBundle'Entity'ProjetInt $descriptions
     */
    public function removeDescription('PublicBundle'Entity'ProjetInt $descriptions)
    {
        $this->descriptions->removeElement($descriptions);
    }
    /**
     * Get descriptions
     *
     * @return 'Doctrine'Common'Collections'Collection 
     */
    public function getDescriptions()
    {
        return $this->descriptions;
    }
    /**
     * Set type
     *
     * @param 'PublicBundle'Entity'Type $type
     * @return Projet
     */
    public function setType('PublicBundle'Entity'Type $type)
    {
        $this->type = $type;
        return $this;
    }
    /**
     * Get type
     *
     * @return 'PublicBundle'Entity'Type 
     */
    public function getType()
    {
        return $this->type;
    }
    /**
     * Add categories
     *
     * @param 'PublicBundle'Entity'Categorie $categories
     * @return Projet
     */
    public function addCategory('PublicBundle'Entity'Categorie $categories)
    {
        $this->categories[] = $categories;
        return $this;
    }
    /**
     * Remove categories
     *
     * @param 'PublicBundle'Entity'Categorie $categories
     */
    public function removeCategory('PublicBundle'Entity'Categorie $categories)
    {
        $this->categories->removeElement($categories);
    }
    /**
     * Get categories
     *
     * @return 'Doctrine'Common'Collections'Collection 
     */
    public function getCategories()
    {
        return $this->categories;
    }


    /**
     * @Assert'File(maxSize="6000000")
     */
    private $fichierFile;
    /**
     * Sets fichier file.
     *
     * @param UploadedFile $fichierFile
     */
    public function setFichierFile(UploadedFile $fichierFile = null)
    {
        $this->fichierFile = $fichierFile;
        //Vérifi s'il y a déja un fichier de projet
        if(isset($this->fichier))
        {
            //Stock l'ancien nom pour l'effacer après la mise à jour
            $this->fichierTemp=$this->fichier;
            $this->fichier=null;
        }
        else
        {
            $this->fichier='initial';
        }
    }
    /**
     * Get fichier file.
     *
     * @return UploadedFile
     */
    public function getFichierFile()
    {
        return $this->fichierFile;
    }


    /**
     * @Assert'File(maxSize="6000000")
     */
    private $imageFile;
    /**
     * Sets image file.
     *
     * @param UploadedFile $imageFile
     */
    public function setImageFile(UploadedFile $imageFile = null)
    {
        $this->imageFile = $imageFile;
        //Vérifi s'il y a déja un fichier d'image
        if(isset($this->image))
        {
            //Stock l'ancien nom pour l'effacer après la mise à jour
            $this->imageTemp=$this->image;
            $this->image=null;
        }
        else
        {
            $this->image='initial';
        }
    }
    /**
     * Get image file.
     *
     * @return UploadedFile
     */
    public function getImageFile()
    {
        return $this->imageFile;
    }

    /**
     * @ORM'PrePersist()
     * @ORM'PreUpdate()
     */
    public function preUpload()
    {
        //S'il y a un fichier pour le projet
        if (null !== $this->getFichierFile())
        {
            //Génère un nom unique
            $nomFichierProjet = sha1(uniqid(mt_rand(), true));
            $this->fichier = $nomFichierProjet.'.'.$this->getFichierFile()->guessExtension();
        }
        //S'il y a un fichier pour l'image
        if (null !== $this->getImageFile())
        {
            //Génère un nom unique
            $nomFichierImage = sha1(uniqid(mt_rand(), true));
            $this->image = $nomFichierImage.'.'.$this->getImageFile()->guessExtension();
        }
    }
    /**
     * @ORM'PostPersist()
     * @ORM'PostUpdate()
     */
    public function upload()
    {
        if (null !== $this->getFichierFile())
        {
            // if there is an error when moving the file, an exception will
            // be automatically thrown by move(). This will properly prevent
            // the entity from being persisted to the database on error
            $this->getFichierFile()->move($this->getUploadRootDirFichier(), $this->fichier);
            //Vérifi s'il y a déja un fichier de projet
            if (isset($this->fichierTemp)) {
                //Efface l'ancien fichier du projet
                unlink($this->getUploadRootDirFichier().'/'.$this->fichierTemp);
                //Efface le chemin temporaire
                $this->fichierTemp = null;
            }
            $this->fichierFile = null;
        }
        if (null !== $this->getImageFile())
        {
            // if there is an error when moving the file, an exception will
            // be automatically thrown by move(). This will properly prevent
            // the entity from being persisted to the database on error
            $this->getImageFile()->move($this->getUploadRootDirImage(), $this->image);
            //Vérifi s'il y a déja un fichier d'image
            if (isset($this->imageTemp)) {
                //Efface l'ancienne image du projet
                unlink($this->getUploadRootDirImage().'/'.$this->imageTemp);
                //Efface le chemin temporaire
                $this->imageTemp = null;
            }
            $this->imageFile = null;
        }  
    }

    /**
     * @ORM'PostRemove()
     */
    public function removeUpload()
    {
        $fichierFile = $this->getAbsolutePathFichier();
        if ($fichierFile) {
            unlink($fichierFile);
        }
        $imageFile = $this->getAbsolutePathImage();
        if ($imageFile) {
            unlink($imageFile);
        }
    }

    public function getAbsolutePathFichier()
    {
        return null === $this->fichier
            ? null
            : $this->getUploadRootDirFichier().'/'.$this->fichier;
    }
    public function getWebPathFichier()
    {
        return null === $this->fichier
            ? null
            : $this->getUploadDirFichier().'/'.$this->fichier;
    }

    public function getAbsolutePathImage()
    {
        return null === $this->image
            ? null
            : $this->getUploadRootDirImage().'/'.$this->image;
    }
    public function getWebPathImage()
    {
        return null === $this->fichier
            ? null
            : $this->getUploadDirImage().'/'.$this->image;
    }

    //Le chemin absolu du répertoire où le fichier du projet se trouve 
    protected function getUploadRootDirFichier()
    {
        return __DIR__.'/../../../web/'.$this->getUploadDirFichier();
    }
    //Le chemin absolu du répertoire où l'image du projet se trouve 
    protected function getUploadRootDirImage()
    {
        return __DIR__.'/../../../web/'.$this->getUploadDirImage();
    }

    protected function getUploadDirFichier()
    {
        return 'bundles/public/projets/'.$this->getType()->getNom();
    }
    protected function getUploadDirImage()
    {
        return 'bundles/public/projets/vignettes';
    }
}

我的projetInt实体:

<?php
namespace PublicBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
/**
 * Projet Inter
 *
 * @ORM'Table(name="pt_projet_int");
 * @ORM'Entity
 * @ORM'Entity(repositoryClass="PublicBundle'Entity'ProjetIntDepot")
 */
class ProjetInt
{
    /**
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    //ID du projet
    protected $id;
    /**
     * @ORM'ManyToOne(targetEntity="Projet", inversedBy="descriptions")
     * @ORM'JoinColumn(name="pro_id_CE", referencedColumnName="id", nullable=false)
     */
    //Clef étrangère du projet associé
    protected $projet;
    /**
     * @ORM'Column(name="pri_lang", type="string", length=2)
    */
    //Langue de la carégorie
    protected $langue;
    /**
     * @ORM'Column(name="pri_nom", type="string", length=30)
     */
    //Nom du produit
    protected $nom;
    /**
     * @ORM'Column(name="pri_description_cours", type="text",length=100)
     */
    //Description cours du projet
    protected $descriptionCours;
    /**
     * @ORM'Column(name="pri_description_complete", type="text",length=250)
     */
    //Description complete du projet
    protected $descriptionComplete;
    /**
     * @ORM'Column(name="pri_roles", type="string",length=60)
     */
    //Roles joués dans la création du projet
    protected $roles;
    /**
     * @ORM'Column(name="pri_aptitudes_developpees", type="string",length=200)
     */
    //Aptitudes développées lors du projet
    protected $aptitudesDeveloppees;

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Set langue
     *
     * @param string $langue
     * @return ProjetInt
     */
    public function setLangue($langue)
    {
        $this->langue = $langue;
        return $this;
    }
    /**
     * Get langue
     *
     * @return string 
     */
    public function getLangue()
    {
        return $this->langue;
    }
    /**
     * Set nom
     *
     * @param string $nom
     * @return ProjetInt
     */
    public function setNom($nom)
    {
        $this->nom = $nom;
        return $this;
    }
    /**
     * Get nom
     *
     * @return string 
     */
    public function getNom()
    {
        return $this->nom;
    }
    /**
     * Set descriptionCours
     *
     * @param string $descriptionCours
     * @return ProjetInt
     */
    public function setDescriptionCours($descriptionCours)
    {
        $this->descriptionCours = $descriptionCours;
        return $this;
    }
    /**
     * Get descriptionCours
     *
     * @return string 
     */
    public function getDescriptionCours()
    {
        return $this->descriptionCours;
    }
    /**
     * Set descriptionComplete
     *
     * @param string $descriptionComplete
     * @return ProjetInt
     */
    public function setDescriptionComplete($descriptionComplete)
    {
        $this->descriptionComplete = $descriptionComplete;
        return $this;
    }
    /**
     * Get descriptionComplete
     *
     * @return string 
     */
    public function getDescriptionComplete()
    {
        return $this->descriptionComplete;
    }
    /**
     * Set roles
     *
     * @param string $roles
     * @return ProjetInt
     */
    public function setRoles($roles)
    {
        $this->roles = $roles;
        return $this;
    }
    /**
     * Get roles
     *
     * @return string 
     */
    public function getRoles()
    {
        return $this->roles;
    }
    /**
     * Set aptitudesDeveloppees
     *
     * @param string $aptitudesDeveloppees
     * @return ProjetInt
     */
    public function setAptitudesDeveloppees($aptitudesDeveloppees)
    {
        $this->aptitudesDeveloppees = $aptitudesDeveloppees;
        return $this;
    }
    /**
     * Get aptitudesDeveloppees
     *
     * @return string 
     */
    public function getAptitudesDeveloppees()
    {
        return $this->aptitudesDeveloppees;
    }
    /**
     * Set projetId
     *
     * @param 'PublicBundle'Entity'Projet $projetId
     * @return ProjetInt
     */
    public function setProjetId('PublicBundle'Entity'Projet $projetId)
    {
        $this->projetId = $projetId;
        return $this;
    }
    /**
     * Get projetId
     *
     * @return 'PublicBundle'Entity'Projet 
     */
    public function getProjetId()
    {
        return $this->projetId;
    }
    /**
     * Set projet
     *
     * @param 'PublicBundle'Entity'Projet $projet
     * @return ProjetInt
     */
    public function setProjet('PublicBundle'Entity'Projet $projet)
    {
        $this->projet = $projet;
        return $this;
    }
    /**
     * Get projet
     *
     * @return 'PublicBundle'Entity'Projet 
     */
    public function getProjet()
    {
        return $this->projet;
    }
}

我的形式:

项目形式:

<?php
namespace AdminBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolver;
Class ProjetType extends AbstractType
{
    public function buildForm(FormBuilderInterface $constructeur, array $options)
    {
        $constructeur
        ->add('imageFile')
        //Doesn't work
        /*->add('descriptions', 'collection', array(
            'type' => new ProjetIntType(),
            'by_reference'=>false,
            'allow_add'=>true,
            'allow_delete'=>true,
        ))*/
        ->add('technologie', 'text')
        ->add('annee', 'text', array('label'=>'année'))
        ->add('type', 'entity', [
            'class'=>'PublicBundle'Entity'Type',
            'property'=>'nom',
            'required'=>true,
        ])
        ->add('fichierFile')
        ->add('largeur', 'text')
        ->add('hauteur', 'text')
        ->add('categories', 'entity', [
            'label'=>'catégorie',
            'class'=>'PublicBundle'Entity'Categorie',
            'property'=>'tag',
            'required'=>true,
            'multiple'=>true,
            'expanded'=>true,
        ])
        ->add('Modifier', 'submit');
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'PublicBundle'Entity'Projet',
        ));
    }
    public function getName()
    {
        return 'projet';
    }
}

projetInt形式:

<?php
namespace AdminBundle'Form'Type;
use Symfony'Component'Form'AbstractType;
use Symfony'Component'Form'FormBuilderInterface;
use Symfony'Component'OptionsResolver'OptionsResolver;
Class ProjetIntType extends AbstractType
{
    public function buildForm(FormBuilderInterface $constructeur, array $options)
    {
        $constructeur
        ->add('langue', 'text')
        ->add('nom', 'text')
        ->add('descriptionCours', 'text')
        ->add('descriptionComplete', 'text')
        ->add('roles', 'text')
        ->add('aptitudesDeveloppees', 'text');
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'PublicBundle'Entity'ProjetInt',
        ));
    }
    public function getName()
    {
        return 'projetInt';
    }
}

'entity'表单字段是用来引用现有实体的,这不是你在这里想要的,'collection'确实是要走的路。

在你的特定情况下,你可能想看看Doctrine的可翻译行为,它会为你省去一些麻烦。

顺便说一句,这是一个很好的做法,用英语写代码,无论你的母语和你正在编码的应用程序的语言,它是有用的,例如,当你把它张贴在StackOverflow;)(我自己用法语编码了很长时间,你会惊讶于你的英语技能提高得有多快)

我终于解决了!

我使用了collection字段,并遵循以下食谱:http://symfony.com/doc/current/cookbook/form/form_collections.html

我只能有一个表单(好吧,技术上是两个表单,因为一个是集合,但无论如何),它用于创建项目和编辑项目。唯一需要改变的是我在controller中创建表单的方式:

<?php
...
public function addAction(Request $request)
  {
    //Create new project
    $nouveauProjet = new Projet();
    $descriptionFr = new ProjetInt();
    $descriptionEn = new ProjetInt();
    $nouveauProjet->addDescription($descriptionFr);
    $nouveauProjet->addDescription($descriptionEn);
    $descriptionFr->setProjet($nouveauProjet);
    $descriptionEn->setProjet($nouveauProjet);
    $form=$this->createForm(new ProjetType(), $nouveauProjet);
    $form->handleRequest($request);
    if($form->isValid())
    {
      //Save the project
      ...
    }
    return $this->render('AdminBundle::ajoutProjet.html.twig',array(
                                      'form'=>$form->createView()
                                    ));
  }
  public function editAction($id, Request $request)
  {
    $project=$this->getDoctrine()->getRepository('PublicBundle:Projet')->findOneById($id);
    $form=$this->createForm(new ProjetType(), $projet);
    $form->handleRequest($request);
    if($form->isValid())
    {
      $em=$this->getDoctrine()->getManager();
      $em->flush();
      $this->get('session')->getFlashBag()->add('confirmation', 'The project was editted');
    }
    return $this->render('AdminBundle::modifierProjet.html.twig',array(
                                                                        'form'=>$form->createView(),
                                                                    ));
  }