【问题标题】:Problems with Symfony embedded formsSymfony 嵌入式表单的问题
【发布时间】:2015-08-31 04:58:02
【问题描述】:

我正在尝试实现以下场景:

拍卖和类别实体(多对一)。 Category 实体与 CategoryAttribute 实体具有一对多的关系,允许将无限数量的各种类型的属性添加到类别中。假设 Cars 类别将具有 Make 和 Year 属性。 CategoryAttribute 实体具有 widgetType 属性,它定义了如何呈现属性(输入、选择等),attributeValues 是属性的数据(填充选择等)和 isRequired 属性来判断属性是否是必需的。到现在为止还挺好。管理属性是小菜一碟但是:

在拍卖方面,当用户从列表中选择给定类别以呈现该类别的所有属性时,我想要填充该类别。这被转换为相关的 AuctionAttribute 实体(多对一到拍卖类中的属性属性)。 AuctionAttribute 具有对 CategoryAttribute 的引用,这是一个用于保存输入或选定值的属性值。

好吧,整个 AJAX 请求和为选定类别填写属性都不是问题。当我提交表格时出现问题。基本上有两个问题。

  1. 我们如何将表单的属性部分绑定到实际表单以进行验证。假设我们选择了 Car 类别并且需要 Make 属性,我们如何验证该属性?

  2. 我们如何将输入的属性绑定到该表单中的 AuctionAttribute 实体?

我知道对于嵌入式表单,我需要连接到 FormEvents::PRE_SUBMIT 事件,但我不确定如何将属性转换为其中的实体。

在代码方面,我有以下几点:

  1. 当获取一个类别的属性时,我创建了一个 AuctionAttributeFormType 并将它渲染到一个 twig 表单助手中,并在 AJAX 请求中返回 HTML:

    $form = $this->createForm(new Type\AuctionAttributeFormType(), null, array('csrf_protection' => false));
    
    foreach ($categoryAttributes as $attribute) {
        $form->add('attribute_'.$attribute->getId(), $attribute->getWidgetType(), array('label' => $attribute->getName(), 'required' => $attribute->isRequired());
    }
    
  2. 提交Auction表单时,我会挂钩PRE_SUBMIT事件以及是否有提交的属性并且它属于类别的属性集,但这是我在卡住之前所做的:

      $builder->addEventListener(
         Form\FormEvents::PRE_SUBMIT, function (Form\FormEvent $event) {
           $auction = $event->getData();
    
              if (null !== $auction['category']) {
              $categoryAttributes = $this
                      ->repository
                      ->findAttributesForCategory($auction['category'])
                      ->getResult();
    
              if (count($categoryAttributes) > 0) {
                  $attribute_values = array();
                  foreach ($categoryAttributes as $attribute) {
                      if (isset($auction['attribute_' . $attribute->getId()])) {
                          $attribute_values[$attribute->getId()] = $auction['attribute_' . $attribute->getId()];
                      }
                  }
              }
          }
      }
    );
    

我需要将 attribute_values 数组中的值获取到绑定到 Auction 实体的 AuctionAttribute 实体中。知道如何实现这一点。我认为应该通过某种数据转换器来完成,但我不确定要转换哪些数据 - 应该是表单 - >添加字段,还是直接触摸填充有数据的拍卖实体。

有什么建议吗?

编辑:

我使用模型转换器使它工作但现在还有另一个问题,当编辑记录时,如果有多个属性,只有第一个填充数据。这是代码的示例要点:

https://gist.github.com/SvetlinStaev/86e066a865478e40718c

【问题讨论】:

  • 您是否尝试过使用模型转换器?如果没有,请回复,我会建议一个答案。您不应该使用表单事件来转换数据。
  • 不,我没用过。我认为任务需要它,但我不确定如何参考表单创建它。
  • 好的,现在写我的答案
  • 在添加之前阅读标签描述!

标签: forms symfony doctrine entities


【解决方案1】:

我的建议不是通过事件侦听器转换提交的数据,而是使用数据转换器,您可以将其附加到表单字段,如下所示:

$formBuilder->add(
   $formBuilder
   ->create('FIELD_NAME', 'FIELD_TYPE', [
      ... FIELD_OPTIONS ...
   ])
   ->addModelTransformer(new SomeModelTransformer())
)

“SomeModelTransformer”类应该如下所示:

class SeatingToNumberTransformer implements DataTransformerInterface
{

    /**
     * Transforms the object from the norm data to model data
     * The norm data is the field value. Say you have an integer field, $normDataObject would be an int.
     * In your case: you need to instantiate several new AuctionAttribute objects and persist them maybe
     */
    public function transform($normDataObject)
    {
        $transformedObject = $this->someTransformAction($normDataObject);
        return $transformedObject;
    }



    /**
     * Reverts the transform
     * in your case: from AuctionAttribute to int 
     */
    public function reverseTransform($modelDataObject)
    {
        $transformedObject = $this->someOtherTransformAction($modelDataObject);
        return $transformedObject;
    }
}

更多信息可以在here找到
如果您需要更多帮助,请告诉我。

【讨论】:

  • 我试过了,但不幸的是它不起作用。我使用 PRE_SUBMIT 事件来查看是否在数据中设置了 categoryId,如果设置了,那么我将 AttributesFormType 类型的属性子表单添加到主表单,并在每个属性的属性表单中添加一个模型转换器。由于某种原因,它在反向转换方法中接收数据,在该方法中,我从属性 id 创建了一个 Attribute 对象。但它不会附加到表单数据中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 2018-10-17
  • 2012-07-26
  • 1970-01-01
相关资源
最近更新 更多