2017-09-13 198 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

我今天更新了我的问题。 –

相关问题