2012-09-21 56 views
2

我使用的Symfony 2.1和條令2.Symfony的2 - 多個表單字段爲一個數據庫行

我負責的兩個主要實體:地點和特徵,他們之間的多對多關係。 數據庫中有很多功能,並按主題對它們進行分組,功能也與具有ManyToOne關係的FeatureCategory實體相關。

這裏的不同實體的代碼:

廣場實體

namespace Mv\PlaceBundle\Entity; 
… 

/** 
* Mv\PlaceBundle\Entity\Place 
* 
* @ORM\Table(name="place") 
* @ORM\Entity(repositoryClass="Mv\PlaceBundle\Entity\Repository\PlaceRepository") 
* @ORM\HasLifecycleCallbacks 
*/ 
class Place 
{ 
    /** 
    * @var integer $id 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var string $name 
    * 
    * @ORM\Column(name="name", type="string", length=255, unique=true) 
    * @Assert\NotBlank 
    */ 
    private $name; 

    /** 
    * @ORM\ManyToMany(targetEntity="\Mv\MainBundle\Entity\Feature") 
    * @ORM\JoinTable(name="places_features", 
    * joinColumns={@ORM\JoinColumn(name="place_id", referencedColumnName="id")}, 
    * inverseJoinColumns={@ORM\JoinColumn(name="feature_id", referencedColumnName="id")} 
    *) 
    */ 
    private $features; 

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

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

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

    /** 
    * Add features 
    * 
    * @param \Mv\MainBundle\Entity\Feature $features 
    * @return Place 
    */ 
    public function addFeature(\Mv\MainBundle\Entity\Feature $features) 
    { 
    $this->features[] = $features; 
    echo 'Add "'.$features.'" - Total '.count($this->features).'<br />'; 
    return $this; 
    } 

    /** 
    * Remove features 
    * 
    * @param \Mv\MainBundle\Entity\Feature $features 
    */ 
    public function removeFeature(\Mv\MainBundle\Entity\Feature $features) 
    { 
    $this->features->removeElement($features); 
    } 

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

    public function __construct() 
    { 
    $this->features = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

特點實體:

namespace Mv\MainBundle\Entity; 
… 

/** 
* @ORM\Entity 
* @ORM\Table(name="feature") 
* @ORM\HasLifecycleCallbacks 
*/ 
class Feature 
{ 
    use KrToolsTraits\PictureTrait; 

    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(name="label", type="string", length=255) 
    * @Assert\NotBlank() 
    */ 
    protected $label; 

    /** 
    * @ORM\ManyToOne(targetEntity="\Mv\MainBundle\Entity\FeatureCategory", inversedBy="features", cascade={"persist"}) 
    * @ORM\JoinColumn(name="category_id", referencedColumnName="id") 
    */ 
    private $category; 

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

    /** 
    * Set label 
    * 
    * @param string $label 
    * @return Feature 
    */ 
    public function setLabel($label) 
    { 
     $this->label = $label; 
     return $this; 
    } 

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

    /** 
    * Set category 
    * 
    * @param Mv\MainBundle\Entity\FeatureCategory $category 
    * @return Feature 
    */ 
    public function setCategory(\Mv\MainBundle\Entity\FeatureCategory $category = null) 
    { 
     $this->category = $category; 
     return $this; 
    } 

    /** 
    * Get category 
    * 
    * @return Mv\MainBundle\Entity\FeatureCategory 
    */ 
    public function getCategory() 
    { 
     return $this->category; 
    } 
} 

FeatureCategory實體:

namespace Mv\MainBundle\Entity; 
... 

/** 
* @ORM\Entity 
* @ORM\Table(name="feature_category") 
*/ 
class FeatureCategory 
{ 
    /** 
    * @ORM\Id 
    * @ORM\Column(type="integer") 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    protected $id; 

    /** 
    * @ORM\Column(name="code", type="string", length=255) 
    * @Assert\NotBlank() 
    */ 
    protected $code; 

    /** 
    * @ORM\Column(name="label", type="string", length=255) 
    * @Assert\NotBlank() 
    */ 
    protected $label; 

    /** 
    * @ORM\OneToMany(targetEntity="\Mv\MainBundle\Entity\Feature", mappedBy="category", cascade={"persist", "remove"}, orphanRemoval=true) 
    * @Assert\Valid() 
    */ 
    private $features; 

    public function __construct() 
    { 
     $this->features = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

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

    /** 
    * Set code 
    * 
    * @param string $code 
    * @return Feature 
    */ 
    public function setCode($code) 
    { 
     $this->code = $code; 
     return $this; 
    } 

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

    /** 
    * Set label 
    * 
    * @param string $label 
    * @return Feature 
    */ 
    public function setLabel($label) 
    { 
     $this->label = $label; 
     return $this; 
    } 

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

    /** 
    * Add features 
    * 
    * @param \Mv\MainBundle\Entity\Feature $features 
    */ 
    public function addFeatures(\Mv\MainBundle\Entity\Feature $features){ 
     $features->setCategory($this); 
     $this->features[] = $features; 
    } 

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

    /* 
    * Set features 
    */ 
    public function setFeatures(\Doctrine\Common\Collections\Collection $features) 
    { 
     foreach ($features as $feature) 
     { 
     $feature->setCategory($this); 
     } 
     $this->features = $features; 
    } 

    /** 
    * Remove features 
    * 
    * @param Mv\MainBundle\Entity\Feature $features 
    */ 
    public function removeFeature(\Mv\MainBundle\Entity\Feature $features) 
    { 
     $this->features->removeElement($features); 
    } 

    /** 
    * Add features 
    * 
    * @param Mv\MainBundle\Entity\Feature $features 
    * @return FeatureCategory 
    */ 
    public function addFeature(\Mv\MainBundle\Entity\Feature $features) 
    { 
     $features->setCategory($this); 
     $this->features[] = $features; 
    } 
} 

功能表已填充完畢,用戶將無法添加功能,只能在表單集合中選擇它們以將它們鏈接到「地點」。 (該功能實體目前僅與地點鏈接,但稍後將與我的應用程序中的其他實體相關,並將包含所有實體可用的所有功能)

在地方表單中,我需要顯示覆選框一個地方可用的功能,但我需要顯示他們按類別分組。 實施例:

訪問數(FeatureCategory - 代碼VIS):

  • 免費(功能)
  • 付費(功能)

口頭語(FeatureCategory - 代碼LAN):

  • 英文(功能)
  • 法語(功能)
  • 西班牙語(功能)

我的想法

使用虛擬表單在我的PlaceType形式,像這樣:

$builder 
    ->add('name') 
    ->add('visit', new FeatureType('VIS'), array(
     'data_class' => 'Mv\PlaceBundle\Entity\Place' 
    )) 
    ->add('language', new FeatureType('LAN'), array(
     'data_class' => 'Mv\PlaceBundle\Entity\Place' 
    )); 

,並創建一個FeatureType虛擬表單,如下所示:

class FeatureType extends AbstractType 
    { 
     protected $codeCat; 

     public function __construct($codeCat) 
     { 
      $this->codeCat = $codeCat; 
     } 

     public function buildForm(FormBuilderInterface $builder, array $options) 
     { 
      $builder 
       ->add('features', 'entity', array(
        'class' => 'MvMainBundle:Feature', 
        'query_builder' => function(EntityRepository $er) 
        { 
         return $er->createQueryBuilder('f') 
           ->leftJoin('f.category', 'c') 
           ->andWhere('c.code = :codeCat') 
           ->setParameter('codeCat', $this->codeCat) 
           ->orderBy('f.position', 'ASC'); 
        }, 
        'expanded' => true, 
        'multiple' => true 
       )); 
     } 

     public function setDefaultOptions(OptionsResolverInterface $resolver) 
     { 
      $resolver->setDefaults(array(
       'virtual' => true 
      )); 
     } 

     public function getName() 
     { 
      return 'features'; 
     } 
    } 

有了這個解決方案,我得到了我想要的,但綁定過程不會保留所有功能。它不是將它們分組,而是隻保留我並堅持最後一組「語言」,並刪除所有的上一個特徵數據。爲了看到它的作用,如果我檢查了5個複選框,它可以很好地進入Place-> addFeature()函數5次,但函數arrayCollection的長度是連續的:1,2,1,2,3。

任何想法如何以另一種方式做到這一點?如果我需要改變模型,我仍然可以做到。 什麼是最好的方式,可重複使用我的未來其他實體也與功能相關,來處理這個問題?

謝謝你們。

回答

0

我認爲你原來的需求只是約模板

所以你不應該調整窗體和實體持久性邏輯來獲得所需的自動生成表單。

你應該回到一個基本形式

$builder 
    ->add('name') 
    ->add('features', 'entity', array(
     'class' => 'MvMainBundle:Feature', 
     'query_builder' => function(EntityRepository $er) { 
       return $er->createQueryBuilder('f') 
       //order by category.xxx, f.position 
      }, 
       'expanded' => true, 
       'multiple' => true 
      )); 

和調整你的form.html.twig

相關問題