对象包装器和表单

时间:2013-04-02 21:48:33

标签: oop design-patterns symfony symfony-forms

我正在开发一个电子商务平台并遇到了困难。基本上,我在我的场景中有Product,Option和OptionValue。产品可能有多个选项,可能有多个值。问题是如何以易于创建和编辑的方式存储它。

问题是我直接引用OptionValue,它是可变的。我需要保留有关Option和OptionValue的不可变信息(例如,如果订单生成且颜色为绿色,即使此选项更改为浅绿色,订单也必须保持显示为绿色)。在这种情况下,我需要保存Option的一些属性(选项名称 - " Colors"例如)和每个OptionValue(每个选项的值 - "红色"例如) 。我认为,它需要一个与现有结构非常相似的结构:引用Option的新类ItemOption和引用OptionValue的ItemOptionValue。

所以,这是我的尝试:

要创建表单以显示我的选项:

class OptionSelectorType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        foreach ($options['product']->getOptions() as $option) {
            $builder->add($option->getId(), 'choice', array('choice_list' => new ObjectChoiceList($option->getValues());));
        }
    }
}

我使用DataTransformer在OrderItemOption的集合中转换OptionValue的集合:

class OrderItemOptionToOptionValueTransformer implements DataTransformerInterface
{ 
    public function transform($lineOptions)
    {
      if(!$lineOptions) {
        return array();
      }
      $values = array();
      foreach($lineOptions as $lineOption) {
        $lineOption->getOption()->getId();
        $values[$id] = array();

        foreach($lineOption->getValues() as $lineOptionValue) {
          $values[$id][] = $lineOptionValue->getOptionValue();
        }
      }

        return $values;
    }

    public function reverseTransform($values)
    {
      $collection = new ArrayCollection();
      foreach($values as $optionId => $optionValues) {
        if(!$optionValues) {
          continue;
        }

        $lineOption = new OrderItemOption();
        $optionValues = is_array($optionValues) ? $optionValues : array($optionValues);
        foreach($optionValues as $optionValue) {
          $lineOptionValue = new OrderItemOptionValue();
          $lineOptionValue->setOptionValue($optionValue);
          $lineOption->addValue($lineOptionValue);
        }

        $lineOption->setOption($optionValue->getOption());
        $collection->add($lineOption);
      }

      return $collection;
    }
}

最后,我的OrderItemType表单:

class OrderItemType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
      $builder->add(
        $builder->create('options', 'option_selector', array('options' => $options['options']))
        ->addModelTransformer(new OrderItemOptionToOptionValueTransformer())
      );
    }
}

一旦OptionValue总是被重新创建,永远不会更新,它对我来说是有效的,但对我来说并不是一个好方法。

你会怎么做?

1 个答案:

答案 0 :(得分:0)

我会保持简单。您可以坚持使用您的结构,但不要动态地改变事物,而是将它们保持在相同的状态。

我的意思是什么?

每当创建一个Option时,创建相应的ItemOption。 OptionValue和ItemOptionValue也是如此。两者之间的关系是一对一的连接,而Option和OptionValue不知道连接的ItemOption和ItemOptionValue。

现在,如果OptionValue发生更改,您可以查询已连接的ItemOptionValue并更改需要更改的内容(取决于内部结构)。

如何存储连接?

使用您已经使用的任何持久性方法。对于数据库的情况,将连接存储在一个表中,如下所示:

CREATE TABLE item_option_to_option (
    optionID INT(10) NOT NULL,
    itemOptionID INT(10) NOT NULL,
    UNIQUE KEY (optionID, itemOptionID)
);

如果可能,我会使用外键将两列链接到表item_optionoption中的相应列。它对OptionValue和ItemOptionValue的作用相同。

如何处理变更?

每当调用OptionValue更改的控制器时,只需更新Item *模型。

如果删除了Option或OptionValue,则删除ItemOption或ItemOptionValue也取决于您。