2015-07-19 228 views
0

我正在研究Symfony 2中的一個表單,我需要一些幫助。該表單用於修改有關項目的信息。我有兩個實體,projet(一個項目)和projetInt(所有需要國際化的文本)。我製作了一個ProjetType表單,它工作正常。如何在Symfony 2中整合多個實體形式

問題來了,當我需要projetInt形式內de projet形式。起初,我嘗試使用收集字段,但遇到了一個我還沒有解決的奇怪錯誤(https://stackoverflow.com/questions/31397195/error-with-the-collection-field-in-form-in-symfony-2)。

問題是,我想要的是projetInt窗體在projet窗體中添加兩次,因爲我的projet文本必須以法語和英語提供。另一件事是我希望這個表單可以用於我的添加projet動作,因爲如果我想修改我的項目,我只需要將項目傳遞給表單,因爲在這兩種情況下,無論是添加還是修改,必要的領域或完全相同。

這是我走到這一步:

我謨實體:

<?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'; 

    } 

} 

回答

0

我終於解決了!

我用收集場,跟着這個食譜: http://symfony.com/doc/current/cookbook/form/form_collections.html

我能有隻有一種形式(當然,因爲一個technicly兩個表單是一個集合,但不管),並且同時用於創建一個項目和編輯一個。唯一改變的是我在控制器中創建表單的方式:

<?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(), 
                    )); 
    } 
0

的「實體」表單字段用來參考現有的實體,這是不是你想要的這裏,「收集」確實是要走的路。

在你的具體情況下,你可能想看看Doctrine的Translatable behavior,它會爲你節省一些頭痛。

順便說一句,不管你的母語和你正在編碼的應用程序的語言,用英文編寫代碼都是一個好習慣,例如當你把它發佈到StackOverflow上時,它是很有用的;) (我自己編碼很長一段時間用法語,你會驚訝你的英語能力會提高多快)。