2017-09-13 195 views
1

我想爲實體創建表單,該實體包含同一實體的兩個集合,但每個集合都在一個屬性中包含具有特定值的實體。Symfony 3 - 具有相同實體的多個表單集合

我的數據庫表看起來像這樣:

Table 1: base 
| id | foo | bar | 
|----|-----|-----| 

Table 2: extended 
| id | table_1_id | type | baz | 
|----|------------|------|-----| 

表1和2是在1:n的關係,因此,「基極」實體可以容納「擴展」實體的任何量。

我已經定義的實體:

class Base { 
    private $id; 
    private $foo; 
    private $baz; 
    private $extendedCollection; 

    /*...*/ 

    public function getTypeA() { 
     $result = new ArrayCollection(); 
     foreach ($extendedCollection->toArray() as $item) { 
      if ($item->getType() == "A") { 
       $result->add($item); 
      } 
     } 
     return $result; 
    } 
    /* respective for type "B" */ 

    public function addExtendedA(Extended $a) { 
     if (!$this->extendedCollection->contains($a)) { 
      $a 
       ->setBase($this) 
       ->setType("A"); 
      $this->extendedCollection->add($a); 
     } 
     return $this; 
    } 
    /* respective for type "B" */ 
} 

class Extended { 
    private $id; 
    private $base; 
    private $type; 
    private $baz; 

    /*...*/ 
} 

最後,我也創建了兩個表單類:

class BaseType extends AbstractType { 
    public function buildForm(FormBuilderInterface $builder, array $options) { 
     $builder 
      ->add('foo') 
      ->add('bar') 
      ->add('typeA', CollectionType::class, array(
       'entry_type' => ExtendedType::class, 
       'entry_options' => array(
        'type' => "A" 
       ), 
       'allow_add' => true, 
       'allow_delete' => true, 
       'required' => false, 
       'by_reference' => false 
      ) 
      ->add('typeB', CollectionType::class, array(
       'entry_type' => ExtendedType::class, 
       'entry_options' => array(
        'type' => "B" 
       ), 
       'allow_add' => true, 
       'allow_delete' => true, 
       'required' => false, 
       'by_reference' => false 
      ); 

      /*...*/ 
    } 
} 

class ExtendedType extends AbstractType { 

    private $type; 

    public function buildForm(FormBuilderInterface $builder, array $options) { 

     $this->type = $options['type'];`enter code here` 
     $builder 
      ->add('type', HiddenType::class, array(
       'data' => $this->type 
      ) 
      ->add('baz'); 
    } 

    public function configureOptions(OptionsResolver $resolver) { 
     $resolver->setDefaults(array(
      'data_class' => Extended::class, 
      'type' => "" 
     )); 
    } 
} 

期望得到的結果如下: 當請求「基地」的實體,數據庫內容被解析爲一個實體,並且「擴展」實體的ArrayCollection按照集合項類型被排序爲兩個集合「A」和「B」,並且這兩個集合都被呈現爲單獨的表單列表。 這工作。

當更新「基本」實體時,兩個「擴展」集合應該融合到新的extendedCollection中,並且實體應該被保留。 這不起作用。

如果我手動添加了一些擴展行到數據庫中,我可以呈現模板,一切都顯示 - 但是,當我嘗試申請通過HTML表單一些變化,一個NoSuchPropertyException被拋出,其中有消息稱​​。我錯過了什麼?我能做些什麼來優化這個模型?

UPDATE 2017年9月14日 我添加了一個setter函數應用新的「擴展」類別:

class Base { 
    /* see above for reference code */ 

    public function setTypeACollection(ArrayCollection $typeAExtended) 
    { 
     $this->setExtendedCollection($typeAExtended, "A"); 
     return $this; 
    } 
    /* Respective for type "B" */ 

    private function setExtendedCollection(ArrayCollection $newExtended, $type) 
    { 
     $newExtendedCollection = new ArrayCollection(); 
     $extendedArray = $this->extendedCollection->toArray(); 
     foreach ($extendedArray as $k => $v) { 
      if ($v->getType() == $type) { 
       unset($extendedArray[$k]); 
      } else { 
       $newExtendedCollection->add($v); 
      } 
     } 
     foreach ($newExtended->toArray() as $newExt) { 
      $newExt->setType($type); 
      $newExtendedCollection->add($item); 
     } 
     $this->extendedCollection = $newExtendedCollection; 
    } 
} 

現在,NoSuchPropertyException走了,但一個新的問題仍然存在: 當我加載基地實體從數據庫中擴展集合被應用乾淨,但通過HTML表單更新實體會導致以下錯誤,具體取決於是否有更改:

  • 無更改:實體以錯誤的方式更新,因爲所有類型「B」都變成類型「A」,因此都顯示在類型「A」收集中。
  • 刪除類型「B」:刪除的類型「B」變爲類型「A」而不是被刪除。
  • 刪除類型「A」:刪除的擴展保留,另外所有類型「B」都變成類型「A」。
  • 添加類型「A」:添加的擴展不是持久的,此外所有類型「B」都變成類型「A」。
  • 添加一個「B」型:一個ORMInvalidArgumentException被拋出,該消息是A new entity was found through the relationship 'Acme\Bundle\Entity\Base#extendedCollection' that was not configured to cascade persist operations for entity: Acme\Bundle\Entity\[email protected] To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Acme\Bundle\Entity\Extended#__toString()' to get a clue.

Extended類包含在引用$base屬性註釋@ORM\ManyToOne(targetEntity="Acme\Bundle\Entity\Base", inversedBy="extendedCollection", cascade={"persist"})

回答

1

表單字段從表單的底層對象/類映射而來,所以當表單組件嘗試將提交的值映射到此屬性時,​​指向Base類中的遺漏屬性typeA

試圖解決它在你Base類中添加setTypeA(Collection $items)方法和手動更新根據typeextendedCollection財產。

+0

我今天更新了我的問題。 –

相關問題