如何在Symfony 2中整合多个实体形式
我正在研究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';
}
}
我终于解决了!
我用收集场,跟着这个食谱: 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(),
));
}
的“实体”表单字段用来参考现有的实体,这是不是你想要的这里,“收集”确实是要走的路。
在你的具体情况下,你可能想看看Doctrine的Translatable behavior,它会为你节省一些头痛。
顺便说一句,不管你的母语和你正在编码的应用程序的语言,用英文编写代码都是一个好习惯,例如当你把它发布到StackOverflow上时,它是很有用的;) (我自己编码很长一段时间用法语,你会惊讶你的英语能力会提高多快)。